From ffb78977ca3c2423870a91d7ebe0d705e5b1ebff Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sat, 6 Jun 2020 19:30:32 +0100 Subject: [PATCH 01/25] GithubTeams: Add New/Remove/Update --- GitHubTeams.ps1 | 360 +++++++++++++++++++++++++ PowerShellForGitHub.psd1 | 9 + Tests/GitHubTeams.tests.ps1 | 505 +++++++++++++++++++++++++++++++++++- 3 files changed, 873 insertions(+), 1 deletion(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 33a632ed..fb00501e 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 @@ -97,6 +100,11 @@ filter Get-GitHubTeam [ValidateNotNullOrEmpty()] [string] $OrganizationName, + [Parameter(ParameterSetName='Organization')] + [Parameter(ParameterSetName='Elements')] + [Parameter(ParameterSetName='Uri')] + [string] $TeamName, + [Parameter( Mandatory, ValueFromPipelineByPropertyName, @@ -273,6 +281,358 @@ 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 or 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 Maintainers + A list of GitHub IDs for organization members who will become team maintainers. + + .PARAMETER RepositoryName + A list 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. + + .OUTPUTS + PSCustomObject + + .EXAMPLE + New-GitHubTeam -OrganizationName PowerShell -TeamName MyTeam + + Creates a new GitHub team in the specified organization +#> + [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 + )] + param + ( + [Parameter(Mandatory, Position = 1)] + [ValidateNotNullOrEmpty()] + [string] $OrganizationName, + + [Parameter(Mandatory, Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $TeamName, + + [string] $Description, + + [string[]] $Maintainers, + + [string[]] $RepositoryName, + + [ValidateSet('Secret','Closed')] + [string] $Privacy, + + [string] $ParentTeamName, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $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('Maintainers')) { $hashBody['maintainers'] = $Maintainers } + if ($PSBoundParameters.ContainsKey('RepositoryName')) { $hashBody['repo_names'] = $RepositoryName } + if ($PSBoundParameters.ContainsKey('Privacy')) { $hashBody['privacy'] = $Privacy.ToLower() } + if ($PSBoundParameters.ContainsKey('ParentTeamName')) + { + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $ParentTeamName + AccessToken = $AccessToken + NoStatus = $NoStatus + Whatif = $false + Confirm = $false + } + $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 +} + +function Update-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. + + .OUTPUTS + PSCustomObject + + .EXAMPLE + Update-GitHubTeam -OrganizationName PowerShell -TeamName MyTeam -Description 'New Description' + + Updates the description for the specified GitHub team in the specified organization. +#> + [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 + )] + param + ( + [Parameter(Mandatory, Position = 1)] + [ValidateNotNullOrEmpty()] + [string] $OrganizationName, + + [Parameter(Mandatory, Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $TeamName, + + [string] $Description, + + [ValidateSet('Secret','Closed')] + [string] $Privacy, + + [string] $ParentTeamName, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{ + OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) + TeamName = (Get-PiiSafeString -PlainText $TeamName) + } + + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $teamName + AccessToken = $AccessToken + NoStatus = $NoStatus + Whatif = $false + Confirm = $false + } + $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 + AccessToken = $AccessToken + NoStatus = $NoStatus + Whatif = $false + Confirm = $false + } + $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 +} + +function Remove-GitHubTeam +{ +<# + .SYNOPSIS + Removes a team within an organization on GitHub. + + .DESCRIPTION + Removes 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 the team is in. + + .PARAMETER TeamName + The name of the 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. + + .OUTPUTS + PSCustomObject + + .EXAMPLE + Remove-GitHubTeam -OrganizationName PowerShell -TeamName MyTeam + + Removes the specified GitHub team from the specified organization +#> + [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, Position = 1)] + [ValidateNotNullOrEmpty()] + [string] $OrganizationName, + + [Parameter(Mandatory, Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $TeamName, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{ + OrganizationName = (Get-PiiSafeString -PlainText $RepositoryName) + TeamName = (Get-PiiSafeString -PlainText $TeamName) + } + + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $TeamName + AccessToken = $AccessToken + NoStatus = $NoStatus + Whatif = $false + Confirm = $false + } + $team = Get-GitHubTeam @getGitHubTeamParms + + $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" + + if ($PSCmdlet.ShouldProcess($TeamName, "Remove Team")) + { + $params = @{ + UriFragment = $uriFragment + Method = 'Delete' + Description = "Deleting $TeamName" + AccessToken = $AccessToken + TelemetryEventName = $MyInvocation.MyCommand.Name + TelemetryProperties = $telemetryProperties + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params + } +} + filter Add-GitHubTeamAdditionalProperties { <# diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 21dd8820..8435e303 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -141,6 +141,7 @@ 'New-GitHubRepositoryBranch', 'New-GitHubRepositoryBranchProtectionRule', 'New-GitHubRepositoryFork', + 'New-GithubTeam', 'Remove-GitHubAssignee', 'Remove-GitHubComment', 'Remove-GitHubGist', @@ -160,6 +161,7 @@ 'Remove-GitHubRepository', 'Remove-GitHubRepositoryBranch' 'Remove-GitHubRepositoryBranchProtectionRule', + 'Remove-GitHubTeam', 'Rename-GitHubGistFile', 'Rename-GitHubRepository', 'Reset-GitHubConfiguration', @@ -192,6 +194,12 @@ 'Test-GitHubOrganizationMember', 'Test-GitHubRepositoryVulnerabilityAlert', 'Unlock-GitHubIssue' + 'Unlock-GitHubIssue', + 'Update-GitHubCurrentUser', + 'Update-GitHubIssue', + 'Update-GitHubLabel', + 'Update-GitHubRepository', + 'Update-GitHubTeam' ) AliasesToExport = @( @@ -214,6 +222,7 @@ 'Delete-GitHubRepository', 'Delete-GitHubRepositoryBranch', 'Delete-GitHubRepositoryBranchProtectionRule', + 'Delete-GitHubTeam', 'Fork-GitHubGist', 'Get-GitHubAsset', 'Get-GitHubBranch', diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index 21658992..ff7ffa36 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -11,13 +11,516 @@ Justification='Suppress false positives in Pester code blocks')] param() +Set-StrictMode -Version 1.0 + # 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 { - # 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' { + + Context 'When getting a GitHub Team by organization' { + BeforeAll { + $repoName = [Guid]::NewGuid().Guid + + $newGithubRepositoryParms = @{ + RepositoryName = $repoName + OrganizationName = $script:organizationName + } + $repo = New-GitHubRepository @newGitHubRepositoryParms + + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + $maintainers = $script:ownerName + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Description = $description + RepositoryName = $repo.full_name + Privacy = $privacy + Maintainers = $maintainers + } + New-GitHubTeam @newGithubTeamParms | Out-Null + + $getGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + } + $team = Get-GitHubTeam @getGitHubTeamParms + } + + It 'Should return an object of the correct type' { + $team | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $team.name | Should -Be $teamName + $team.description | Should -Be $description + $team.organization.login | Should -Be $script:organizationName + $team.parent | Should -BeNullOrEmpty + $team.members_count | Should -Be 1 + $team.repos_count | Should -Be 1 + $team.privacy | Should -Be $privacy + } + + AfterAll { + if ($team) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $team.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + + Context 'When getting a GitHub Team by repository' { + BeforeAll -ScriptBlock { + $repoName = [Guid]::NewGuid().Guid + + $newGithubRepositoryParms = @{ + RepositoryName = $repoName + OrganizationName = $script:organizationName + } + $repo = New-GitHubRepository @newGitHubRepositoryParms + + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Description = $description + RepositoryName = $repo.full_name + Privacy = $privacy + } + New-GitHubTeam @newGithubTeamParms | Out-Null + + $getGitHubTeamParms = @{ + OwnerName = $script:organizationName + RepositoryName = $repoName + } + $team = Get-GitHubTeam @getGitHubTeamParms + } + + It 'Should return an object of the correct type' { + $team | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $team.name | Should -Be $teamName + $team.description | Should -Be $description + $team.parent | Should -BeNullOrEmpty + $team.privacy | Should -Be $privacy + } + + AfterAll { + if ($repo) + { + $removeGitHubRepositoryParms = @{ + OwnerName = $script:organizationName + RepositoryName = $repo.name + Confirm = $false + } + Remove-GitHubRepository @removeGitHubRepositoryParms + } + + if ($team) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $team.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + + Context 'When getting a GitHub Team by TeamId' { + BeforeAll { + $repoName = [Guid]::NewGuid().Guid + + $newGithubRepositoryParms = @{ + RepositoryName = $repoName + OrganizationName = $script:organizationName + } + $repo = New-GitHubRepository @newGitHubRepositoryParms + + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + $maintainers = $script:ownerName + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Description = $description + RepositoryName = $repo.full_name + Privacy = $privacy + Maintainers = $maintainers + } + $newTeam = New-GitHubTeam @newGithubTeamParms + + $getGitHubTeamParms = @{ + TeamId = $newTeam.id + } + $team = Get-GitHubTeam @getGitHubTeamParms + } + + It 'Should return an object of the correct type' { + $team | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $team.name | Should -Be $teamName + $team.description | Should -Be $description + $team.organization.login | Should -Be $script:organizationName + $team.parent | Should -BeNullOrEmpty + $team.members_count | Should -Be 1 + $team.repos_count | Should -Be 1 + $team.privacy | Should -Be $privacy + } + + AfterAll { + if ($team) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $team.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + } + + Describe 'GitHubTeams\New-GitHubTeam' { + + Context 'When creating a new GitHub team with default settings' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + } + $team = New-GitHubTeam @newGithubTeamParms + } + + It 'Should return an object of the correct type' { + $team | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $team.name | Should -Be $teamName + $team.organization.login | Should -Be $OrganizationName + $team.description | Should -BeNullOrEmpty + $team.parent | Should -BeNullOrEmpty + $team.members_count | Should -Be 1 + $team.repos_count | Should -Be 0 + } + + AfterAll { + if ($team) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $team.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + + Context 'When creating a new GitHub team with all possible settings' { + BeforeAll { + $repoName = [Guid]::NewGuid().Guid + + $newGithubRepositoryParms = @{ + RepositoryName = $repoName + OrganizationName = $script:organizationName + } + $repo = New-GitHubRepository @newGitHubRepositoryParms + + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + $maintainers = $script:ownerName + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Description = $description + RepositoryName = $repo.full_name + Privacy = $privacy + Maintainers = $maintainers + } + $team = New-GitHubTeam @newGithubTeamParms + } + + It 'Should return an object of the correct type' { + $team | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $team.name | Should -Be $teamName + $team.organization.login | Should -Be $OrganizationName + $team.description | Should -Be $description + $team.parent | Should -BeNullOrEmpty + $team.members_count | Should -Be 1 + $team.repos_count | Should -Be 1 + $team.privacy | Should -Be $privacy + } + + AfterAll { + if ($repo) + { + $removeGitHubRepositoryParms = @{ + OwnerName = $script:organizationName + RepositoryName = $repo.name + Confirm = $false + } + Remove-GitHubRepository @removeGitHubRepositoryParms + } + if ($team) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $team.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + + Context 'When creating a child GitHub team' { + BeforeAll { + + $parentTeamName = [Guid]::NewGuid().Guid + $privacy= 'Closed' + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $parentTeamName + Privacy = $privacy + } + $parentTeam = New-GitHubTeam @newGithubTeamParms + + $childTeamName = [Guid]::NewGuid().Guid + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $childTeamName + ParentTeamName = $parentTeamName + Privacy = $privacy + } + $childTeam = New-GitHubTeam @newGithubTeamParms + } + + It 'Should return an object of the correct type' { + $childTeam | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $childTeam.name | Should -Be $childTeamName + $childTeam.organization.login | Should -Be $OrganizationName + $childTeam.parent.name | Should -Be $parentTeamName + $childTeam.privacy | Should -Be $privacy + } + + AfterAll { + if ($childTeam) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $childTeam.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + + if ($parentTeam) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $parentTeam.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + } + + Describe 'GitHubTeams\Update-GitHubTeam' { + + Context 'When updating a Child GitHub team' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'Closed' + $parentTeamName = [Guid]::NewGuid().Guid + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $parentTeamName + Privacy = $privacy + } + $parentTeam = New-GitHubTeam @newGithubTeamParms + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Privacy = $privacy + } + $team = New-GitHubTeam @newGithubTeamParms + + $updateGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Description = $description + Privacy = $privacy + ParentTeamName = $parentTeamName + } + + $updatedTeam = Update-GitHubTeam @updateGitHubTeamParms + } + + It 'Should return an object of the correct type' { + $updatedTeam | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $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 + } + + AfterAll { + if ($team) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $team.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + + if ($parentTeam) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $parentTeam.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + + Context 'When updating a non-nested GitHub team' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'Closed' + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Privacy = 'Secret' + } + $team = New-GitHubTeam @newGithubTeamParms + + $updateGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Description = $description + Privacy = $privacy + } + + $updatedTeam = Update-GitHubTeam @updateGitHubTeamParms + } + + It 'Should return an object of the correct type' { + $updatedTeam | Should -BeOfType PSCustomObject + } + + It 'Should return the correct properties' { + $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 + } + + AfterAll { + if ($team) + { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $team.name + Confirm = $false + } + Remove-GitHubTeam @RemoveGitHubTeamParms + } + } + } + } + + Describe 'GitHubTeams\Remove-GitHubTeam' { + + Context 'When removing a GitHub team' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + } + $team = New-GitHubTeam @newGithubTeamParms + } + + It 'Should not throw an exception' { + $removeGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Confirm = $false + } + { Remove-GitHubTeam @RemoveGitHubTeamParms } | + Should -Not -Throw + + } + + It 'Should have removed the team' { + $getGitHubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + } + { Get-GitHubTeam @getGitHubTeamParms } | Should -Throw + } + } + } } finally { From 2792007d671d1983e3419e69f19227687600303c Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sat, 6 Jun 2020 19:52:13 +0100 Subject: [PATCH 02/25] Update USAGE.md --- USAGE.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/USAGE.md b/USAGE.md index 71eaf035..aa4f262b 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) @@ -478,6 +487,58 @@ Remove-GitHubRepositoryBranch -OwnerName microsoft -RepositoryName PowerShellFor ---------- +### 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 @@ -1091,3 +1152,4 @@ $issue | New-GitHubIssueComment -Body $CommentBody # Close issue $issue | Set-GitHubIssue -State Closed ``` + From 2e51de1458a341d9690024b49112af8573046569 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sun, 7 Jun 2020 12:11:20 +0100 Subject: [PATCH 03/25] Update SuppressMessageAttributes --- GitHubTeams.ps1 | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index fb00501e..941c9036 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -332,13 +332,15 @@ function New-GitHubTeam Creates a new GitHub team in the specified organization #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', - Justification = 'Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.')] + 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.')] + 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 - )] + )] param ( [Parameter(Mandatory, Position = 1)] @@ -455,14 +457,16 @@ function Update-GitHubTeam Updates the description for the specified GitHub team in the specified organization. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', - Justification = 'Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.')] + 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 - )] - param + 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 + )] + param ( [Parameter(Mandatory, Position = 1)] [ValidateNotNullOrEmpty()] @@ -574,14 +578,16 @@ function Remove-GitHubTeam Removes the specified GitHub team from the specified organization #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', - Justification = 'Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.')] + 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.')] + 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 ( @@ -598,8 +604,6 @@ function Remove-GitHubTeam [switch] $NoStatus ) - Write-InvocationLog -Invocation $MyInvocation - $telemetryProperties = @{ OrganizationName = (Get-PiiSafeString -PlainText $RepositoryName) TeamName = (Get-PiiSafeString -PlainText $TeamName) @@ -619,6 +623,8 @@ function Remove-GitHubTeam if ($PSCmdlet.ShouldProcess($TeamName, "Remove Team")) { + Write-InvocationLog -Invocation $MyInvocation + $params = @{ UriFragment = $uriFragment Method = 'Delete' From fd64dfd7b4037eb45aaea4253d9f9e82192e54fb Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sun, 7 Jun 2020 12:32:12 +0100 Subject: [PATCH 04/25] Add conditional parms to Get-GitHubTeam calls --- GitHubTeams.ps1 | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 941c9036..1018c53f 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -389,11 +389,15 @@ function New-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName TeamName = $ParentTeamName - AccessToken = $AccessToken - NoStatus = $NoStatus 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 } @@ -498,11 +502,15 @@ function Update-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName TeamName = $teamName - AccessToken = $AccessToken - NoStatus = $NoStatus 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)" @@ -518,11 +526,15 @@ function Update-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName TeamName = $ParentTeamName - AccessToken = $AccessToken - NoStatus = $NoStatus 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 @@ -612,11 +624,15 @@ function Remove-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName TeamName = $TeamName - AccessToken = $AccessToken - NoStatus = $NoStatus 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)" From e96f3e9cb69882957c455e725bc154520b8b7b5e Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sun, 7 Jun 2020 15:48:45 +0100 Subject: [PATCH 05/25] Add Remove-GitHubTeams -Force switch --- GitHubTeams.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 1018c53f..a27aeb5a 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -571,6 +571,9 @@ function Remove-GitHubTeam .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. @@ -611,6 +614,8 @@ function Remove-GitHubTeam [ValidateNotNullOrEmpty()] [string] $TeamName, + [switch] $Force, + [string] $AccessToken, [switch] $NoStatus @@ -637,6 +642,10 @@ function Remove-GitHubTeam $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" + if ($Force -and -not $Confirm){ + $ConfirmPreference = 'None' + } + if ($PSCmdlet.ShouldProcess($TeamName, "Remove Team")) { Write-InvocationLog -Invocation $MyInvocation From 8b4dd87141c664c8c032cb1613a850f655269741 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sun, 7 Jun 2020 22:31:19 +0100 Subject: [PATCH 06/25] Fix formatting --- GitHubTeams.ps1 | 70 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index a27aeb5a..8515a003 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -157,11 +157,41 @@ filter Get-GitHubTeam 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties - 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + '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) + { + throw "Team '$TeamName' not found" + } + 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 @@ -392,13 +422,16 @@ function New-GitHubTeam Whatif = $false Confirm = $false } - if ($PSBoundParameters.ContainsKey('AccessToken')) { + if ($PSBoundParameters.ContainsKey('AccessToken')) + { $getGitHubTeamParms['AccessToken'] = $AccessToken } - if ($PSBoundParameters.ContainsKey('NoStatus')) { + if ($PSBoundParameters.ContainsKey('NoStatus')) + { $getGitHubTeamParms['NoStatus'] = $NoStatus } $team = Get-GitHubTeam @getGitHubTeamParms + $hashBody['parent_team_id'] = $team.id } @@ -410,7 +443,8 @@ function New-GitHubTeam AccessToken = $AccessToken TelemetryEventName = $MyInvocation.MyCommand.Name TelemetryProperties = $telemetryProperties - NoStatus = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` + -Name NoStatus -ConfigValueName DefaultNoStatus) } return Invoke-GHRestMethod @params @@ -505,10 +539,12 @@ function Update-GitHubTeam Whatif = $false Confirm = $false } - if ($PSBoundParameters.ContainsKey('AccessToken')) { + if ($PSBoundParameters.ContainsKey('AccessToken')) + { $getGitHubTeamParms['AccessToken'] = $AccessToken } - if ($PSBoundParameters.ContainsKey('NoStatus')) { + if ($PSBoundParameters.ContainsKey('NoStatus')) + { $getGitHubTeamParms['NoStatus'] = $NoStatus } $team = Get-GitHubTeam @getGitHubTeamParms @@ -529,10 +565,12 @@ function Update-GitHubTeam Whatif = $false Confirm = $false } - if ($PSBoundParameters.ContainsKey('AccessToken')) { + if ($PSBoundParameters.ContainsKey('AccessToken')) + { $getGitHubTeamParms['AccessToken'] = $AccessToken } - if ($PSBoundParameters.ContainsKey('NoStatus')) { + if ($PSBoundParameters.ContainsKey('NoStatus')) + { $getGitHubTeamParms['NoStatus'] = $NoStatus } $team = Get-GitHubTeam @getGitHubTeamParms @@ -548,7 +586,8 @@ function Update-GitHubTeam AccessToken = $AccessToken TelemetryEventName = $MyInvocation.MyCommand.Name TelemetryProperties = $telemetryProperties - NoStatus = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` + -Name NoStatus -ConfigValueName DefaultNoStatus) } return Invoke-GHRestMethod @params @@ -632,10 +671,12 @@ function Remove-GitHubTeam Whatif = $false Confirm = $false } - if ($PSBoundParameters.ContainsKey('AccessToken')) { + if ($PSBoundParameters.ContainsKey('AccessToken')) + { $getGitHubTeamParms['AccessToken'] = $AccessToken } - if ($PSBoundParameters.ContainsKey('NoStatus')) { + if ($PSBoundParameters.ContainsKey('NoStatus')) + { $getGitHubTeamParms['NoStatus'] = $NoStatus } $team = Get-GitHubTeam @getGitHubTeamParms @@ -657,7 +698,8 @@ function Remove-GitHubTeam AccessToken = $AccessToken TelemetryEventName = $MyInvocation.MyCommand.Name TelemetryProperties = $telemetryProperties - NoStatus = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` + -Name NoStatus -ConfigValueName DefaultNoStatus) } return Invoke-GHRestMethod @params From 564bef4d8aeecf954d43a0045765d7ff3143b9df Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Wed, 10 Jun 2020 21:01:44 +0100 Subject: [PATCH 07/25] Remove redundant Invocation parameters --- GitHubTeams.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 8515a003..78194481 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -397,7 +397,7 @@ function New-GitHubTeam [switch] $NoStatus ) - Write-InvocationLog -Invocation $MyInvocation + Write-InvocationLog $telemetryProperties = @{ OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) @@ -526,7 +526,7 @@ function Update-GitHubTeam [switch] $NoStatus ) - Write-InvocationLog -Invocation $MyInvocation + Write-InvocationLog $telemetryProperties = @{ OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) @@ -689,7 +689,7 @@ function Remove-GitHubTeam if ($PSCmdlet.ShouldProcess($TeamName, "Remove Team")) { - Write-InvocationLog -Invocation $MyInvocation + Write-InvocationLog $params = @{ UriFragment = $uriFragment From af45afd192867f190f812e3ae717b1f4aa4d66d3 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Wed, 10 Jun 2020 21:43:08 +0100 Subject: [PATCH 08/25] Update examples --- GitHubTeams.ps1 | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 78194481..6ec8c8e2 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -357,9 +357,9 @@ function New-GitHubTeam PSCustomObject .EXAMPLE - New-GitHubTeam -OrganizationName PowerShell -TeamName MyTeam + New-GitHubTeam -OrganizationName PowerShell -TeamName 'Developers' - Creates a new GitHub team in the specified organization + Creates a new GitHub team called 'Developers' in the 'PowerShell' organization. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'Methods called within here make use of PSShouldProcess, and the switch @@ -490,9 +490,9 @@ function Update-GitHubTeam PSCustomObject .EXAMPLE - Update-GitHubTeam -OrganizationName PowerShell -TeamName MyTeam -Description 'New Description' + Update-GitHubTeam -OrganizationName PowerShell -TeamName Developers -Description 'New Description' - Updates the description for the specified GitHub team in the specified organization. + Updates the description for the 'Developers' GitHub team in the 'PowerShell' organization. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'Methods called within here make use of PSShouldProcess, and the switch @@ -627,9 +627,14 @@ function Remove-GitHubTeam PSCustomObject .EXAMPLE - Remove-GitHubTeam -OrganizationName PowerShell -TeamName MyTeam + Remove-GitHubTeam -OrganizationName PowerShell -TeamName Developers - Removes the specified GitHub team from the specified organization + 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. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'Methods called within here make use of PSShouldProcess, and the switch From 4ebaa9d4529efbf5846a887761209c0654304cb0 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Wed, 10 Jun 2020 21:44:39 +0100 Subject: [PATCH 09/25] Update Force condition --- GitHubTeams.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 6ec8c8e2..4ee3ed93 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -688,7 +688,8 @@ function Remove-GitHubTeam $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" - if ($Force -and -not $Confirm){ + if ($Force -and (-not $Confirm)) + { $ConfirmPreference = 'None' } From 9907a00f78700855e68a505728a0c5ff6cb04446 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Fri, 19 Jun 2020 18:33:54 +0100 Subject: [PATCH 10/25] Add pipeline support --- GitHubTeams.ps1 | 77 ++++++++++++--- Tests/GitHubTeams.tests.ps1 | 182 +++++++++++++++++------------------- 2 files changed, 150 insertions(+), 109 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 4ee3ed93..b1563103 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -311,7 +311,7 @@ filter Get-GitHubTeamMember return (Invoke-GHRestMethodMultipleResult @params | Add-GitHubUserAdditionalProperties) } -function New-GitHubTeam +filter New-GitHubTeam { <# .SYNOPSIS @@ -353,8 +353,11 @@ function New-GitHubTeam 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 + .OUTPUTS - PSCustomObject + GitHub.Team .EXAMPLE New-GitHubTeam -OrganizationName PowerShell -TeamName 'Developers' @@ -371,13 +374,19 @@ function New-GitHubTeam SupportsShouldProcess, PositionalBinding = $false )] + [OutputType({$script:GitHubTeamTypeName})] param ( - [Parameter(Mandatory, Position = 1)] + [Parameter( + Mandatory, + Position = 1)] [ValidateNotNullOrEmpty()] [string] $OrganizationName, - [Parameter(Mandatory, Position = 2)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 2)] [ValidateNotNullOrEmpty()] [string] $TeamName, @@ -447,10 +456,10 @@ function New-GitHubTeam -Name NoStatus -ConfigValueName DefaultNoStatus) } - return Invoke-GHRestMethod @params + return (Invoke-GHRestMethod @params | Add-GitHubTeamAdditionalProperties) } -function Update-GitHubTeam +filter Update-GitHubTeam { <# .SYNOPSIS @@ -486,8 +495,12 @@ function Update-GitHubTeam 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 + System.String + .OUTPUTS - PSCustomObject + GitHub.User .EXAMPLE Update-GitHubTeam -OrganizationName PowerShell -TeamName Developers -Description 'New Description' @@ -504,13 +517,20 @@ function Update-GitHubTeam SupportsShouldProcess, PositionalBinding = $false )] + [OutputType({$script:GitHubTeamTypeName})] param ( - [Parameter(Mandatory, Position = 1)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] [ValidateNotNullOrEmpty()] [string] $OrganizationName, - [Parameter(Mandatory, Position = 2)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 2)] [ValidateNotNullOrEmpty()] [string] $TeamName, @@ -590,10 +610,10 @@ function Update-GitHubTeam -Name NoStatus -ConfigValueName DefaultNoStatus) } - return Invoke-GHRestMethod @params + return (Invoke-GHRestMethod @params | Add-GitHubTeamAdditionalProperties) } -function Remove-GitHubTeam +filter Remove-GitHubTeam { <# .SYNOPSIS @@ -624,7 +644,7 @@ function Remove-GitHubTeam If not supplied here, the DefaultNoStatus configuration property value will be used. .OUTPUTS - PSCustomObject + None .EXAMPLE Remove-GitHubTeam -OrganizationName PowerShell -TeamName Developers @@ -650,11 +670,19 @@ function Remove-GitHubTeam [Alias('Delete-GitHubTeam')] param ( - [Parameter(Mandatory, Position = 1)] + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] [ValidateNotNullOrEmpty()] [string] $OrganizationName, - [Parameter(Mandatory, Position = 2)] + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] [ValidateNotNullOrEmpty()] [string] $TeamName, @@ -708,7 +736,7 @@ function Remove-GitHubTeam -Name NoStatus -ConfigValueName DefaultNoStatus) } - return Invoke-GHRestMethod @params + Invoke-GHRestMethod @params | Out-Null } } @@ -753,6 +781,25 @@ 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') + + if ($item.html_url -match "^https?://$hostName/orgs/([^/]+)/?([^/]+)?(?:/.*)?$") + { + $organizationName = $Matches[1] + } + else + { + $organizationName = '' + } + } + 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/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index ff7ffa36..c4a6e590 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -29,58 +29,52 @@ try } Describe 'GitHubTeams\Get-GitHubTeam' { + BeforeAll { + $organizationName = $script:organizationName + } Context 'When getting a GitHub Team by organization' { BeforeAll { - $repoName = [Guid]::NewGuid().Guid - - $newGithubRepositoryParms = @{ - RepositoryName = $repoName - OrganizationName = $script:organizationName - } - $repo = New-GitHubRepository @newGitHubRepositoryParms - $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' $privacy = 'closed' $maintainers = $script:ownerName $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Description = $description - RepositoryName = $repo.full_name Privacy = $privacy Maintainers = $maintainers } New-GitHubTeam @newGithubTeamParms | Out-Null $getGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName } $team = Get-GitHubTeam @getGitHubTeamParms } - It 'Should return an object of the correct type' { - $team | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + 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 $script:organizationName + $team.organization.login | Should -Be $organizationName $team.parent | Should -BeNullOrEmpty $team.members_count | Should -Be 1 - $team.repos_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 ($team) { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $team.name Confirm = $false } @@ -95,7 +89,7 @@ try $newGithubRepositoryParms = @{ RepositoryName = $repoName - OrganizationName = $script:organizationName + OrganizationName = $organizationName } $repo = New-GitHubRepository @newGitHubRepositoryParms @@ -104,7 +98,7 @@ try $privacy = 'closed' $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Description = $description RepositoryName = $repo.full_name @@ -113,28 +107,28 @@ try New-GitHubTeam @newGithubTeamParms | Out-Null $getGitHubTeamParms = @{ - OwnerName = $script:organizationName + OwnerName = $organizationName RepositoryName = $repoName } $team = Get-GitHubTeam @getGitHubTeamParms } - It 'Should return an object of the correct type' { - $team | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + 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 } AfterAll { if ($repo) { $removeGitHubRepositoryParms = @{ - OwnerName = $script:organizationName + OwnerName = $organizationName RepositoryName = $repo.name Confirm = $false } @@ -144,7 +138,7 @@ try if ($team) { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $team.name Confirm = $false } @@ -155,14 +149,6 @@ try Context 'When getting a GitHub Team by TeamId' { BeforeAll { - $repoName = [Guid]::NewGuid().Guid - - $newGithubRepositoryParms = @{ - RepositoryName = $repoName - OrganizationName = $script:organizationName - } - $repo = New-GitHubRepository @newGitHubRepositoryParms - $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' $privacy = 'closed' @@ -172,7 +158,6 @@ try OrganizationName = $script:organizationName TeamName = $teamName Description = $description - RepositoryName = $repo.full_name Privacy = $privacy Maintainers = $maintainers } @@ -184,18 +169,18 @@ try $team = Get-GitHubTeam @getGitHubTeamParms } - It 'Should return an object of the correct type' { - $team | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + 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 $script:organizationName + $team.organization.login | Should -Be $organizationName $team.parent | Should -BeNullOrEmpty $team.members_count | Should -Be 1 - $team.repos_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 { @@ -213,28 +198,31 @@ try } 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 = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName } $team = New-GitHubTeam @newGithubTeamParms } - It 'Should return an object of the correct type' { - $team | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + It 'Should have the expected type and additional properties' { + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' $team.name | Should -Be $teamName - $team.organization.login | Should -Be $OrganizationName $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 } AfterAll { @@ -276,34 +264,35 @@ try $team = New-GitHubTeam @newGithubTeamParms } - It 'Should return an object of the correct type' { - $team | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + It 'Should have the expected type and additional properties' { + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' $team.name | Should -Be $teamName - $team.organization.login | Should -Be $OrganizationName $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 } AfterAll { if ($repo) { $removeGitHubRepositoryParms = @{ - OwnerName = $script:organizationName + OwnerName = $organizationName RepositoryName = $repo.name Confirm = $false } Remove-GitHubRepository @removeGitHubRepositoryParms } + if ($team) { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $team.name Confirm = $false } @@ -314,12 +303,11 @@ try Context 'When creating a child GitHub team' { BeforeAll { - $parentTeamName = [Guid]::NewGuid().Guid $privacy= 'Closed' $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $parentTeamName Privacy = $privacy } @@ -328,7 +316,7 @@ try $childTeamName = [Guid]::NewGuid().Guid $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $childTeamName ParentTeamName = $parentTeamName Privacy = $privacy @@ -336,22 +324,22 @@ try $childTeam = New-GitHubTeam @newGithubTeamParms } - It 'Should return an object of the correct type' { - $childTeam | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + 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.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 ($childTeam) { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $childTeam.name Confirm = $false } @@ -361,7 +349,7 @@ try if ($parentTeam) { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $parentTeam.name Confirm = $false } @@ -372,30 +360,33 @@ try } Describe 'GitHubTeams\Update-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' - $parentTeamName = [Guid]::NewGuid().Guid $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $parentTeamName Privacy = $privacy } $parentTeam = New-GitHubTeam @newGithubTeamParms $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Privacy = $privacy } $team = New-GitHubTeam @newGithubTeamParms $updateGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Description = $description Privacy = $privacy @@ -405,23 +396,23 @@ try $updatedTeam = Update-GitHubTeam @updateGitHubTeamParms } - It 'Should return an object of the correct type' { - $updatedTeam | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + 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.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 } AfterAll { if ($team) { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $team.name Confirm = $false } @@ -431,7 +422,7 @@ try if ($parentTeam) { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $parentTeam.name Confirm = $false } @@ -440,21 +431,21 @@ try } } - Context 'When updating a non-nested GitHub team' { + Context 'When updating a non-child GitHub team' { BeforeAll { $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' $privacy = 'Closed' $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Privacy = 'Secret' } $team = New-GitHubTeam @newGithubTeamParms $updateGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Description = $description Privacy = $privacy @@ -463,16 +454,16 @@ try $updatedTeam = Update-GitHubTeam @updateGitHubTeamParms } - It 'Should return an object of the correct type' { - $updatedTeam | Should -BeOfType PSCustomObject - } - - It 'Should return the correct properties' { + 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 { @@ -490,12 +481,15 @@ try } Describe 'GitHubTeams\Remove-GitHubTeam' { + BeforeAll { + $organizationName = $script:organizationName + } Context 'When removing a GitHub team' { BeforeAll { $teamName = [Guid]::NewGuid().Guid $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName } $team = New-GitHubTeam @newGithubTeamParms @@ -503,7 +497,7 @@ try It 'Should not throw an exception' { $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Confirm = $false } @@ -514,7 +508,7 @@ try It 'Should have removed the team' { $getGitHubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName } { Get-GitHubTeam @getGitHubTeamParms } | Should -Throw From b71c9f10bd6d6f22fdfe957ac52b103c106c9e02 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sat, 20 Jun 2020 10:32:38 +0100 Subject: [PATCH 11/25] Fix review comments --- GitHubTeams.ps1 | 158 +++++++++++++++++++----------- PowerShellForGitHub.psd1 | 6 +- Tests/GitHubTeams.tests.ps1 | 190 +++++++++++++++++------------------- 3 files changed, 194 insertions(+), 160 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index b1563103..dc515f64 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -157,8 +157,7 @@ filter Get-GitHubTeam 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties - 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue ` - -Name NoStatus -ConfigValueName DefaultNoStatus) + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) } $result = Invoke-GHRestMethodMultipleResult @params | Add-GitHubTeamAdditionalProperties @@ -173,8 +172,8 @@ filter Get-GitHubTeam } else { - $uriFragment = "/teams/$($team.Id)" - $description = "Getting team $($team.Id)" + $uriFragment = "/teams/$($team.id)" + $description = "Getting team $($team.id)" $params = @{ UriFragment = $uriFragment @@ -311,14 +310,14 @@ filter Get-GitHubTeamMember return (Invoke-GHRestMethodMultipleResult @params | Add-GitHubUserAdditionalProperties) } -filter New-GitHubTeam +function New-GitHubTeam { <# .SYNOPSIS Creates a team within an organization on GitHub. .DESCRIPTION - Creates a team or within an organization on GitHub. + Creates a team within an organization on GitHub. The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub @@ -331,11 +330,11 @@ filter New-GitHubTeam .PARAMETER Description The description for the team. - .PARAMETER Maintainers + .PARAMETER MaintainerName A list of GitHub IDs for organization members who will become team maintainers. - .PARAMETER RepositoryName - A list of repositories to add the team to. + .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. @@ -355,6 +354,7 @@ filter New-GitHubTeam .INPUTS System.String + GitHub.User .OUTPUTS GitHub.Team @@ -363,6 +363,18 @@ filter New-GitHubTeam 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 @@ -385,18 +397,20 @@ filter New-GitHubTeam [Parameter( Mandatory, - ValueFromPipelineByPropertyName, + ValueFromPipeline, Position = 2)] [ValidateNotNullOrEmpty()] [string] $TeamName, [string] $Description, - [string[]] $Maintainers, + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('UserName')] + [string[]] $MaintainerName, - [string[]] $RepositoryName, + [string[]] $RepositoryFullName, - [ValidateSet('Secret','Closed')] + [ValidateSet('Secret', 'Closed')] [string] $Privacy, [string] $ParentTeamName, @@ -406,60 +420,80 @@ filter New-GitHubTeam [switch] $NoStatus ) - Write-InvocationLog - - $telemetryProperties = @{ - OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) - TeamName = (Get-PiiSafeString -PlainText $TeamName) + begin + { + $maintainerNames = @() } - $uriFragment = "/orgs/$OrganizationName/teams" - - $hashBody = @{ - name = $TeamName + process + { + foreach ($user in $MaintainerName) + { + $maintainerNames += $user + } } - if ($PSBoundParameters.ContainsKey('Description')) { $hashBody['description'] = $Description } - if ($PSBoundParameters.ContainsKey('Maintainers')) { $hashBody['maintainers'] = $Maintainers } - if ($PSBoundParameters.ContainsKey('RepositoryName')) { $hashBody['repo_names'] = $RepositoryName } - if ($PSBoundParameters.ContainsKey('Privacy')) { $hashBody['privacy'] = $Privacy.ToLower() } - if ($PSBoundParameters.ContainsKey('ParentTeamName')) + end { - $getGitHubTeamParms = @{ - OrganizationName = $OrganizationName - TeamName = $ParentTeamName - Whatif = $false - Confirm = $false + Write-InvocationLog + + $telemetryProperties = @{ + OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) + TeamName = (Get-PiiSafeString -PlainText $TeamName) } - if ($PSBoundParameters.ContainsKey('AccessToken')) + + $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) { - $getGitHubTeamParms['AccessToken'] = $AccessToken + $hashBody['maintainers'] = $maintainerNames } - if ($PSBoundParameters.ContainsKey('NoStatus')) + if ($PSBoundParameters.ContainsKey('ParentTeamName')) { - $getGitHubTeamParms['NoStatus'] = $NoStatus + $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 } - $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) + } - $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) } - - return (Invoke-GHRestMethod @params | Add-GitHubTeamAdditionalProperties) } -filter Update-GitHubTeam +filter Set-GitHubTeam { <# .SYNOPSIS @@ -503,9 +537,15 @@ filter Update-GitHubTeam GitHub.User .EXAMPLE - Update-GitHubTeam -OrganizationName PowerShell -TeamName Developers -Description 'New Description' + 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 @@ -567,6 +607,7 @@ filter Update-GitHubTeam { $getGitHubTeamParms['NoStatus'] = $NoStatus } + $team = Get-GitHubTeam @getGitHubTeamParms $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" @@ -617,10 +658,10 @@ filter Remove-GitHubTeam { <# .SYNOPSIS - Removes a team within an organization on GitHub. + Removes a team from an organization on GitHub. .DESCRIPTION - Removes a team within an organization on GitHub. + Removes a team from an organization on GitHub. The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub @@ -655,6 +696,12 @@ filter Remove-GitHubTeam 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 @@ -712,6 +759,7 @@ filter Remove-GitHubTeam { $getGitHubTeamParms['NoStatus'] = $NoStatus } + $team = Get-GitHubTeam @getGitHubTeamParms $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 8435e303..14a366e3 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -141,7 +141,7 @@ 'New-GitHubRepositoryBranch', 'New-GitHubRepositoryBranchProtectionRule', 'New-GitHubRepositoryFork', - 'New-GithubTeam', + 'New-GitHubTeam', 'Remove-GitHubAssignee', 'Remove-GitHubComment', 'Remove-GitHubGist', @@ -187,6 +187,7 @@ 'Set-GitHubReleaseAsset', 'Set-GitHubRepository', 'Set-GitHubRepositoryTopic', + 'Set-GitHubTeam', 'Split-GitHubUri', 'Test-GitHubAssignee', 'Test-GitHubAuthenticationConfigured', @@ -198,8 +199,7 @@ 'Update-GitHubCurrentUser', 'Update-GitHubIssue', 'Update-GitHubLabel', - 'Update-GitHubRepository', - 'Update-GitHubTeam' + 'Update-GitHubRepository' ) AliasesToExport = @( diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index c4a6e590..e9218aa2 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -11,8 +11,6 @@ Justification='Suppress false positives in Pester code blocks')] param() -Set-StrictMode -Version 1.0 - # 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') @@ -38,21 +36,23 @@ try $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' $privacy = 'closed' - $maintainers = $script:ownerName + $MaintainerName = $script:ownerName $newGithubTeamParms = @{ OrganizationName = $organizationName TeamName = $teamName Description = $description Privacy = $privacy - Maintainers = $maintainers + MaintainerName = $MaintainerName } + New-GitHubTeam @newGithubTeamParms | Out-Null $getGitHubTeamParms = @{ OrganizationName = $organizationName TeamName = $teamName } + $team = Get-GitHubTeam @getGitHubTeamParms } @@ -70,27 +70,27 @@ try $team.OrganizationName | Should -Be $organizationName } + It 'Should support pipeline input for the organization parameter' { + { $team | Get-GitHubTeam -WhatIf } | Should -Not -Throw + } + AfterAll { - if ($team) + if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $team.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $team | Remove-GitHubTeam -Force } } } Context 'When getting a GitHub Team by repository' { - BeforeAll -ScriptBlock { + BeforeAll { $repoName = [Guid]::NewGuid().Guid $newGithubRepositoryParms = @{ RepositoryName = $repoName OrganizationName = $organizationName } + $repo = New-GitHubRepository @newGitHubRepositoryParms $teamName = [Guid]::NewGuid().Guid @@ -101,15 +101,17 @@ try OrganizationName = $organizationName TeamName = $teamName Description = $description - RepositoryName = $repo.full_name + RepositoryFullName = $repo.full_name Privacy = $privacy } + New-GitHubTeam @newGithubTeamParms | Out-Null $getGitHubTeamParms = @{ OwnerName = $organizationName RepositoryName = $repoName } + $team = Get-GitHubTeam @getGitHubTeamParms } @@ -124,25 +126,19 @@ try $team.OrganizationName | Should -Be $organizationName } + It 'Should support pipeline input for the uri parameter' { + { $repo | Get-GitHubTeam -WhatIf } | Should -Not -Throw + } + AfterAll { - if ($repo) + if (Get-Variable -Name repo -ErrorAction SilentlyContinue) { - $removeGitHubRepositoryParms = @{ - OwnerName = $organizationName - RepositoryName = $repo.name - Confirm = $false - } - Remove-GitHubRepository @removeGitHubRepositoryParms + $repo | Remove-GitHubRepository -Force } - if ($team) + if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $team.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $team | Remove-GitHubTeam -Force } } } @@ -152,20 +148,22 @@ try $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' $privacy = 'closed' - $maintainers = $script:ownerName + $MaintainerName = $script:ownerName $newGithubTeamParms = @{ OrganizationName = $script:organizationName TeamName = $teamName Description = $description Privacy = $privacy - Maintainers = $maintainers + MaintainerName = $MaintainerName } + $newTeam = New-GitHubTeam @newGithubTeamParms $getGitHubTeamParms = @{ TeamId = $newTeam.id } + $team = Get-GitHubTeam @getGitHubTeamParms } @@ -184,14 +182,9 @@ try } AfterAll { - if ($team) + if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName - TeamName = $team.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $team | Remove-GitHubTeam -Force } } } @@ -209,6 +202,7 @@ try OrganizationName = $organizationName TeamName = $teamName } + $team = New-GitHubTeam @newGithubTeamParms } @@ -225,15 +219,15 @@ try $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 ($team) + if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName - TeamName = $team.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $team | Remove-GitHubTeam -Force } } } @@ -244,23 +238,26 @@ try $newGithubRepositoryParms = @{ RepositoryName = $repoName - OrganizationName = $script:organizationName + OrganizationName = $organizationName } + $repo = New-GitHubRepository @newGitHubRepositoryParms + $maintainer = Get-GitHubUser -UserName $script:ownerName + $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' $privacy = 'closed' - $maintainers = $script:ownerName $newGithubTeamParms = @{ - OrganizationName = $script:organizationName + OrganizationName = $organizationName TeamName = $teamName Description = $description - RepositoryName = $repo.full_name + RepositoryFullName = $repo.full_name Privacy = $privacy - Maintainers = $maintainers + MaintainerName = $maintainer.UserName } + $team = New-GitHubTeam @newGithubTeamParms } @@ -278,25 +275,24 @@ try $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 ($repo) + if (Get-Variable -Name repo -ErrorAction SilentlyContinue) { - $removeGitHubRepositoryParms = @{ - OwnerName = $organizationName - RepositoryName = $repo.name - Confirm = $false - } - Remove-GitHubRepository @removeGitHubRepositoryParms + $repo | Remove-GitHubRepository -Force } - if ($team) + if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $team.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $team | Remove-GitHubTeam -Force } } } @@ -311,6 +307,7 @@ try TeamName = $parentTeamName Privacy = $privacy } + $parentTeam = New-GitHubTeam @newGithubTeamParms $childTeamName = [Guid]::NewGuid().Guid @@ -321,6 +318,7 @@ try ParentTeamName = $parentTeamName Privacy = $privacy } + $childTeam = New-GitHubTeam @newGithubTeamParms } @@ -336,30 +334,20 @@ try } AfterAll { - if ($childTeam) + if (Get-Variable -Name childTeam -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $childTeam.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $childTeam | Remove-GitHubTeam -Force } - if ($parentTeam) + if (Get-Variable -Name parentTeam -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $parentTeam.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $parentTeam | Remove-GitHubTeam -Force } } } } - Describe 'GitHubTeams\Update-GitHubTeam' { + Describe 'GitHubTeams\Set-GitHubTeam' { BeforeAll { $organizationName = $script:organizationName } @@ -376,6 +364,7 @@ try TeamName = $parentTeamName Privacy = $privacy } + $parentTeam = New-GitHubTeam @newGithubTeamParms $newGithubTeamParms = @{ @@ -383,6 +372,7 @@ try TeamName = $teamName Privacy = $privacy } + $team = New-GitHubTeam @newGithubTeamParms $updateGitHubTeamParms = @{ @@ -393,7 +383,7 @@ try ParentTeamName = $parentTeamName } - $updatedTeam = Update-GitHubTeam @updateGitHubTeamParms + $updatedTeam = Set-GitHubTeam @updateGitHubTeamParms } It 'Should have the expected type and additional properties' { @@ -408,25 +398,20 @@ try $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 ($team) + if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $team.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $team | Remove-GitHubTeam -Force } - if ($parentTeam) + if (Get-Variable -Name parentTeam -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $parentTeam.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $parentTeam | Remove-GitHubTeam -Force } } } @@ -442,6 +427,7 @@ try TeamName = $teamName Privacy = 'Secret' } + $team = New-GitHubTeam @newGithubTeamParms $updateGitHubTeamParms = @{ @@ -451,7 +437,7 @@ try Privacy = $privacy } - $updatedTeam = Update-GitHubTeam @updateGitHubTeamParms + $updatedTeam = Set-GitHubTeam @updateGitHubTeamParms } It 'Should have the expected type and additional properties' { @@ -467,14 +453,9 @@ try } AfterAll { - if ($team) + if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - $removeGitHubTeamParms = @{ - OrganizationName = $script:organizationName - TeamName = $team.name - Confirm = $false - } - Remove-GitHubTeam @RemoveGitHubTeamParms + $team | Remove-GitHubTeam -Force } } } @@ -492,18 +473,22 @@ try 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 + { Remove-GitHubTeam @RemoveGitHubTeamParms } | Should -Not -Throw } It 'Should have removed the team' { @@ -511,6 +496,7 @@ try OrganizationName = $organizationName TeamName = $teamName } + { Get-GitHubTeam @getGitHubTeamParms } | Should -Throw } } From 6301ebdf77cd681a2919910ff64f1e4b0d79f24e Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sat, 27 Jun 2020 21:42:37 +0100 Subject: [PATCH 12/25] Fix review comments --- GitHubTeams.ps1 | 20 ++++++++++++-------- USAGE.md | 16 ++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index dc515f64..18c53e1c 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -168,7 +168,9 @@ filter Get-GitHubTeam if ($null -eq $team) { - throw "Team '$TeamName' not found" + $message = "Team '$TeamName' not found" + Write-Log -Message $message -Level Error + throw $message } else { @@ -531,10 +533,9 @@ filter Set-GitHubTeam .INPUTS GitHub.Team - System.String .OUTPUTS - GitHub.User + GitHub.Team .EXAMPLE Set-GitHubTeam -OrganizationName PowerShell -TeamName Developers -Description 'New Description' @@ -634,6 +635,7 @@ filter Set-GitHubTeam { $getGitHubTeamParms['NoStatus'] = $NoStatus } + $team = Get-GitHubTeam @getGitHubTeamParms $hashBody['parent_team_id'] = $team.id @@ -684,6 +686,10 @@ filter Remove-GitHubTeam 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 @@ -837,15 +843,13 @@ filter Add-GitHubTeamAdditionalProperties { $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName') - if ($item.html_url -match "^https?://$hostName/orgs/([^/]+)/?([^/]+)?(?:/.*)?$") + $organizationName = [String]::Empty + if ($item.html_url -match "^https?://$hostName/orgs/([^/]+)/.*$") { $organizationName = $Matches[1] } - else - { - $organizationName = '' - } } + Add-Member -InputObject $item -Name 'OrganizationName' -value $organizationName -MemberType NoteProperty -Force # Apply these properties to any embedded parent teams as well. diff --git a/USAGE.md b/USAGE.md index aa4f262b..8411ff7e 100644 --- a/USAGE.md +++ b/USAGE.md @@ -492,49 +492,49 @@ Remove-GitHubRepositoryBranch -OwnerName microsoft -RepositoryName PowerShellFor #### Getting teams in an Organization ```powershell -Get-GitHubTeam -OrganizationName Microsoft +Get-GitHubTeam -OrganizationName microsoft ``` #### Getting teams assigned to a repository ```powershell -Get-GitHubTeam -OwnerName Microsoft -RepositoryName PowerShellForGitHub +Get-GitHubTeam -OwnerName microsoft -RepositoryName PowerShellForGitHub ``` #### Getting a team by team name ```powershell -Get-GitHubTeam -OrganizationName Microsoft -TeamName MyTeam +Get-GitHubTeam -OrganizationName microsoft -TeamName MyTeam ``` #### Getting a team by team id ```powershell -Get-GitHubTeam -OrganizationName Microsoft -TeamId 378661 +Get-GitHubTeam -OrganizationName microsoft -TeamId 378661 ``` #### Creating a team ```powershell -New-GitHubTeam -OrganizationName Microsoft -TeamName MyTeam -Description 'Team Description' +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 +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 +Update-GitHubTeam -OrganizationName microsoft -TeamName MyChildTeam -Description 'Team Description' -ParentTeamName MyTeam ``` #### Removing a team ```powershell -Remove-GitHubTeam -OrganizationName Microsoft -TeamName MyTeam +Remove-GitHubTeam -OrganizationName microsoft -TeamName MyTeam ``` ---------- From 51e368c68a7752789b3aa9e4857b7e3c477aa134 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Thu, 16 Jul 2020 17:13:41 +0100 Subject: [PATCH 13/25] Fix review comments --- GitHubTeams.ps1 | 17 ++++++++++++----- Tests/GitHubTeams.tests.ps1 | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 18c53e1c..27d2f011 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -333,10 +333,10 @@ function New-GitHubTeam The description for the team. .PARAMETER MaintainerName - A list of GitHub IDs for organization members who will become team maintainers. + A list of GitHub user names 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 RepositoryName + The name of repositories to add the team to. .PARAMETER Privacy The level of privacy this team should have. @@ -410,7 +410,7 @@ function New-GitHubTeam [Alias('UserName')] [string[]] $MaintainerName, - [string[]] $RepositoryFullName, + [string[]] $RepositoryName, [ValidateSet('Secret', 'Closed')] [string] $Privacy, @@ -451,7 +451,14 @@ function New-GitHubTeam } if ($PSBoundParameters.ContainsKey('Description')) { $hashBody['description'] = $Description } - if ($PSBoundParameters.ContainsKey('RepositoryFullName')) { $hashBody['repo_names'] = $RepositoryFullName } + if ($PSBoundParameters.ContainsKey('RepositoryFullName')) { + $repositoryFullName = @() + foreach ($repository in $RepositoryName) + { + $repositoryFullName += "$OrganizationName/$Repository" + } + $hashBody['repo_names'] = $repositoryFullName } + } if ($PSBoundParameters.ContainsKey('Privacy')) { $hashBody['privacy'] = $Privacy.ToLower() } if ($MaintainerName.Count -gt 0) { diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index e9218aa2..0a9eb353 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -101,7 +101,7 @@ try OrganizationName = $organizationName TeamName = $teamName Description = $description - RepositoryFullName = $repo.full_name + RepositoryName = $repoName Privacy = $privacy } @@ -253,7 +253,7 @@ try OrganizationName = $organizationName TeamName = $teamName Description = $description - RepositoryFullName = $repo.full_name + RepositoryName = $repoName Privacy = $privacy MaintainerName = $maintainer.UserName } From c02d94108e8d6a64b751f112b1da1d68afebedd8 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Fri, 17 Jul 2020 22:19:03 +0100 Subject: [PATCH 14/25] Fix review comments --- GitHubTeams.ps1 | 6 ++++-- PowerShellForGitHub.psd1 | 5 ----- Tests/GitHubTeams.tests.ps1 | 3 ++- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 27d2f011..782a571c 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -393,6 +393,7 @@ function New-GitHubTeam ( [Parameter( Mandatory, + ValueFromPipelineByPropertyName, Position = 1)] [ValidateNotNullOrEmpty()] [string] $OrganizationName, @@ -539,6 +540,7 @@ filter Set-GitHubTeam If not supplied here, the DefaultNoStatus configuration property value will be used. .INPUTS + GitHub.Organization GitHub.Team .OUTPUTS @@ -693,8 +695,8 @@ filter Remove-GitHubTeam the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. - .INPUTS + GitHub.Organization GitHub.Team .OUTPUTS @@ -842,6 +844,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 + $organizationName = [String]::Empty if ($item.organization) { $organizationName = $item.organization.login @@ -850,7 +853,6 @@ filter Add-GitHubTeamAdditionalProperties { $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName') - $organizationName = [String]::Empty if ($item.html_url -match "^https?://$hostName/orgs/([^/]+)/.*$") { $organizationName = $Matches[1] diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 14a366e3..26bcdfd5 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -195,11 +195,6 @@ 'Test-GitHubOrganizationMember', 'Test-GitHubRepositoryVulnerabilityAlert', 'Unlock-GitHubIssue' - 'Unlock-GitHubIssue', - 'Update-GitHubCurrentUser', - 'Update-GitHubIssue', - 'Update-GitHubLabel', - 'Update-GitHubRepository' ) AliasesToExport = @( diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index 0a9eb353..7f9a4d89 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -280,6 +280,7 @@ try OrganizationName = $organizationName TeamName = $teamName } + { $maintainer | New-GitHubTeam @newGithubTeamParms -WhatIf } | Should -Not -Throw } @@ -300,7 +301,7 @@ try Context 'When creating a child GitHub team' { BeforeAll { $parentTeamName = [Guid]::NewGuid().Guid - $privacy= 'Closed' + $privacy = 'Closed' $newGithubTeamParms = @{ OrganizationName = $organizationName From 40b6a71a42f8fe045a4244987fff046ee0e91992 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Fri, 17 Jul 2020 22:29:20 +0100 Subject: [PATCH 15/25] Update psd1 --- PowerShellForGitHub.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 26bcdfd5..42088ff4 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -1,4 +1,4 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. +# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. @{ From 154dd0d036d083b816bb43fc329f163ad2360d8e Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Fri, 17 Jul 2020 23:08:12 +0100 Subject: [PATCH 16/25] Fix review comments --- GitHubTeams.ps1 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 782a571c..8cd9c6b6 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -3,6 +3,7 @@ @{ GitHubTeamTypeName = 'GitHub.Team' + GitHubTeamSummaryTypeName = 'GitHub.TeamSummary' }.GetEnumerator() | ForEach-Object { Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value } @@ -71,12 +72,15 @@ filter Get-GitHubTeam .OUTPUTS GitHub.Team + GitHub.TeamSummary .EXAMPLE Get-GitHubTeam -OrganizationName PowerShell #> [CmdletBinding(DefaultParameterSetName = 'Elements')] - [OutputType({$script:GitHubTeamTypeName})] + [OutputType( + {$script:GitHubTeamTypeName}, + {$script:GitHubTeamSummaryTypeName})] [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 ( @@ -160,7 +164,8 @@ filter Get-GitHubTeam 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) } - $result = Invoke-GHRestMethodMultipleResult @params | Add-GitHubTeamAdditionalProperties + $result = Invoke-GHRestMethodMultipleResult @params | + Add-GitHubTeamAdditionalProperties -TypeName $script:GitHubTeamSummaryTypeName if ($PSBoundParameters.ContainsKey('TeamName')) { @@ -452,13 +457,14 @@ function New-GitHubTeam } if ($PSBoundParameters.ContainsKey('Description')) { $hashBody['description'] = $Description } - if ($PSBoundParameters.ContainsKey('RepositoryFullName')) { + if ($PSBoundParameters.ContainsKey('RepositoryFullName')) + { $repositoryFullName = @() foreach ($repository in $RepositoryName) { $repositoryFullName += "$OrganizationName/$Repository" } - $hashBody['repo_names'] = $repositoryFullName } + $hashBody['repo_names'] = $repositoryFullName } if ($PSBoundParameters.ContainsKey('Privacy')) { $hashBody['privacy'] = $Privacy.ToLower() } if ($MaintainerName.Count -gt 0) From 54434e09189c31057fcf1d9eb14ece5f43c3f44d Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Fri, 17 Jul 2020 23:08:26 +0100 Subject: [PATCH 17/25] Add Team formatters --- Formatters/GitHubTeams.Format.ps1xml | 80 ++++++++++++++++++++++++++++ PowerShellForGitHub.psd1 | 1 + 2 files changed, 81 insertions(+) create mode 100644 Formatters/GitHubTeams.Format.ps1xml diff --git a/Formatters/GitHubTeams.Format.ps1xml b/Formatters/GitHubTeams.Format.ps1xml new file mode 100644 index 00000000..7b08c7d6 --- /dev/null +++ b/Formatters/GitHubTeams.Format.ps1xml @@ -0,0 +1,80 @@ + + + + + + GitHub.TeamSummary + + GitHub.TeamSummary + + + + + + + name + + + description + + + privacy + + + permission + + + OrganizationName + + + + + + + + + GitHub.Team + + GitHub.Team + + + + + + + name + + + description + + + privacy + + + permission + + + created_at + + + updated_at + + + members_count + + + repos_count + + + parent + + + OrganizationName + + + + + + + + diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 42088ff4..10944b72 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -19,6 +19,7 @@ 'Formatters/GitHubGists.Format.ps1xml', 'Formatters/GitHubReleases.Format.ps1xml' 'Formatters/GitHubRepositories.Format.ps1xml' + 'Formatters/GitHubTeams.Format.ps1xml' ) # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess From 10171f6961963716ce280bfe98095e0b7f35997a Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sat, 18 Jul 2020 12:45:24 +0100 Subject: [PATCH 18/25] Fix review comments --- GitHubTeams.ps1 | 47 +++--- Tests/GitHubTeams.tests.ps1 | 323 +++++++++++++++++++++++++++++------- 2 files changed, 278 insertions(+), 92 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 8cd9c6b6..0c9ed2e6 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -127,6 +127,7 @@ filter Get-GitHubTeam $uriFragment = [String]::Empty $description = [String]::Empty + $teamType = [String]::Empty if ($PSCmdlet.ParameterSetName -in ('Elements', 'Uri')) { $elements = Resolve-RepositoryElements @@ -138,6 +139,7 @@ filter Get-GitHubTeam $uriFragment = "/repos/$OwnerName/$RepositoryName/teams" $description = "Getting teams for $RepositoryName" + $teamType = $script:GitHubTeamSummaryTypeName } elseif ($PSCmdlet.ParameterSetName -eq 'Organization') { @@ -145,6 +147,7 @@ filter Get-GitHubTeam $uriFragment = "/orgs/$OrganizationName/teams" $description = "Getting teams in $OrganizationName" + $teamType = $script:GitHubTeamSummaryTypeName } else { @@ -152,6 +155,7 @@ filter Get-GitHubTeam $uriFragment = "/teams/$TeamId" $description = "Getting team $TeamId" + $teamType = $script:GitHubTeamTypeName } $params = @{ @@ -165,7 +169,7 @@ filter Get-GitHubTeam } $result = Invoke-GHRestMethodMultipleResult @params | - Add-GitHubTeamAdditionalProperties -TypeName $script:GitHubTeamSummaryTypeName + Add-GitHubTeamAdditionalProperties -TypeName $teamType if ($PSBoundParameters.ContainsKey('TeamName')) { @@ -179,8 +183,8 @@ filter Get-GitHubTeam } else { - $uriFragment = "/teams/$($team.id)" - $description = "Getting team $($team.id)" + $uriFragment = "/orgs/$($team.OrganizationName)/teams/$($team.slug)" + $description = "Getting team $($team.slug)" $params = @{ UriFragment = $uriFragment @@ -360,8 +364,9 @@ function New-GitHubTeam If not supplied here, the DefaultNoStatus configuration property value will be used. .INPUTS - System.String + GitHub.Team GitHub.User + System.String .OUTPUTS GitHub.Team @@ -457,14 +462,14 @@ function New-GitHubTeam } if ($PSBoundParameters.ContainsKey('Description')) { $hashBody['description'] = $Description } - if ($PSBoundParameters.ContainsKey('RepositoryFullName')) + if ($PSBoundParameters.ContainsKey('RepositoryName')) { - $repositoryFullName = @() + $repositoryFullNames = @() foreach ($repository in $RepositoryName) { - $repositoryFullName += "$OrganizationName/$Repository" + $repositoryFullNames += "$OrganizationName/$repository" } - $hashBody['repo_names'] = $repositoryFullName + $hashBody['repo_names'] = $repositoryFullNames } if ($PSBoundParameters.ContainsKey('Privacy')) { $hashBody['privacy'] = $Privacy.ToLower() } if ($MaintainerName.Count -gt 0) @@ -573,7 +578,7 @@ filter Set-GitHubTeam SupportsShouldProcess, PositionalBinding = $false )] - [OutputType({$script:GitHubTeamTypeName})] + [OutputType( { $script:GitHubTeamTypeName } )] param ( [Parameter( @@ -611,7 +616,6 @@ filter Set-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName - TeamName = $teamName Whatif = $false Confirm = $false } @@ -624,7 +628,9 @@ filter Set-GitHubTeam $getGitHubTeamParms['NoStatus'] = $NoStatus } - $team = Get-GitHubTeam @getGitHubTeamParms + $orgTeams = Get-GitHubTeam @getGitHubTeamParms + + $team = $orgTeams | Where-Object -Property name -eq $TeamName $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" @@ -636,24 +642,9 @@ filter Set-GitHubTeam 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 + $parentTeam = $orgTeams | Where-Object -Property name -eq $ParentTeamName - $hashBody['parent_team_id'] = $team.id + $hashBody['parent_team_id'] = $parentTeam.id } $params = @{ diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index 7f9a4d89..f8da6b13 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -15,6 +15,8 @@ param() $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent . (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1') +Set-StrictMode -Version 1.0 + try { # Define Script-scoped, readonly, hidden variables. @@ -48,30 +50,59 @@ try New-GitHubTeam @newGithubTeamParms | Out-Null - $getGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $teamName - } + $orgTeams = Get-GitHubTeam -OrganizationName $organizationName - $team = Get-GitHubTeam @getGitHubTeamParms + $team = $orgTeams | Where-Object -Property name -eq $teamName } It 'Should have the expected type and additional properties' { - $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.TeamSummary' $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 + Context 'When specifying the "TeamName" parameter' { + BeforeAll { + $team = Get-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } + + 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.created_at | Should -Not -BeNullOrEmpty + $team.updated_at | Should -Not -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 + } + } + + Context 'When specifying the "OrganizationName" parameter 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.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 + } } AfterAll { @@ -86,12 +117,7 @@ try BeforeAll { $repoName = [Guid]::NewGuid().Guid - $newGithubRepositoryParms = @{ - RepositoryName = $repoName - OrganizationName = $organizationName - } - - $repo = New-GitHubRepository @newGitHubRepositoryParms + $repo = New-GitHubRepository -RepositoryName $repoName -OrganizationName $organizationName $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' @@ -107,16 +133,12 @@ try New-GitHubTeam @newGithubTeamParms | Out-Null - $getGitHubTeamParms = @{ - OwnerName = $organizationName - RepositoryName = $repoName - } - - $team = Get-GitHubTeam @getGitHubTeamParms + $orgTeams = Get-GitHubTeam -OwnerName $organizationName -RepositoryName $repoName + $team = $orgTeams | Where-Object -Property name -eq $teamName } It 'Should have the expected type and additional properties' { - $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.TeamSummary' $team.name | Should -Be $teamName $team.description | Should -Be $description $team.parent | Should -BeNullOrEmpty @@ -126,8 +148,54 @@ try $team.OrganizationName | Should -Be $organizationName } - It 'Should support pipeline input for the uri parameter' { - { $repo | Get-GitHubTeam -WhatIf } | Should -Not -Throw + Context 'When specifying the "TeamName" parameter' { + BeforeAll { + $getGitHubTeamParms = @{ + OwnerName = $organizationName + RepositoryName = $repoName + 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.parent | Should -BeNullOrEmpty + $team.privacy | Should -Be $privacy + $team.created_at | Should -Not -BeNullOrEmpty + $team.updated_at | Should -Not -BeNullOrEmpty + $team.members_count | Should -Be 1 + $team.repos_count | Should -Be 1 + $team.TeamName | Should -Be $teamName + $team.TeamId | Should -Be $team.id + $team.OrganizationName | Should -Be $organizationName + } + } + + Context 'When specifying the "Uri" parameter through the pipeline' { + BeforeAll { + $orgTeams = $repo | Get-GitHubTeam -TeamName $teamName + $team = $orgTeams | Where-Object -Property name -eq $teamName + } + + 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.created_at | Should -Not -BeNullOrEmpty + $team.updated_at | Should -Not -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 + } } AfterAll { @@ -160,11 +228,7 @@ try $newTeam = New-GitHubTeam @newGithubTeamParms - $getGitHubTeamParms = @{ - TeamId = $newTeam.id - } - - $team = Get-GitHubTeam @getGitHubTeamParms + $team = Get-GitHubTeam -TeamId $newTeam.id } It 'Should have the expected type and additional properties' { @@ -173,6 +237,8 @@ try $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 @@ -219,11 +285,6 @@ try $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) { @@ -275,16 +336,6 @@ try $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) { @@ -346,6 +397,107 @@ try } } } + + Context 'When specifying the "Organization" parameter through the pipeline' { + BeforeAll { + $teamName1 = [Guid]::NewGuid().Guid + $teamName2 = [Guid]::NewGuid().Guid + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName1 + } + + $team1 = New-GitHubTeam @newGithubTeamParms + + $team2 = $team1 | New-GitHubTeam -TeamName $teamName2 + } + + 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 + } + + AfterAll { + if (Get-Variable -Name team1 -ErrorAction SilentlyContinue) + { + $team1 | Remove-GitHubTeam -Force + } + + if (Get-Variable -Name team2 -ErrorAction SilentlyContinue) + { + $team2 | Remove-GitHubTeam -Force + } + } + } + + Context 'When specifying the "TeamName" parameter through the pipeline' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + + $team = $teamName | New-GitHubTeam -OrganizationName $organizationName + } + + It 'Should have the expected type and additional properties' { + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $team.name | Should -Be $teamName + $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.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 + } + } + } + + Context 'When specifying the "MaintainerName" parameter through the pipeline' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $maintainer = Get-GitHubUser -UserName $script:ownerName + + $team = $maintainer | New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } + + It 'Should have the expected type and additional properties' { + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $team.name | Should -Be $teamName + $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.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\Set-GitHubTeam' { @@ -399,11 +551,6 @@ try $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) { @@ -448,6 +595,10 @@ try $updatedTeam.description | Should -Be $description $updatedTeam.parent.name | Should -BeNullOrEmpty $updatedTeam.privacy | Should -Be $privacy + $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 $teamName $updatedTeam.TeamId | Should -Be $team.id $updatedTeam.OrganizationName | Should -Be $organizationName @@ -460,6 +611,44 @@ try } } } + + Context 'When specifying the "Organization" and "TeamName" parameters through the pipeline' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + } + + $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + + $updatedTeam = $team | Set-GitHubTeam -Description $description + } + + 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.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 $teamName + $updatedTeam.TeamId | Should -Be $updatedTeam.id + $updatedTeam.OrganizationName | Should -Be $organizationName + } + + AfterAll { + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + } + } } Describe 'GitHubTeams\Remove-GitHubTeam' { @@ -470,16 +659,8 @@ try 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 + $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName } It 'Should not throw an exception' { @@ -493,12 +674,26 @@ try } It 'Should have removed the team' { - $getGitHubTeamParms = @{ - OrganizationName = $organizationName - TeamName = $teamName + { Get-GitHubTeam -OrganizationName $organizationName -TeamName $teamName } | + Should -Throw + } + } + + Context 'When specifying the "Organization" and "TeamName" parameters through the pipeline' { + 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 } - { Get-GitHubTeam @getGitHubTeamParms } | Should -Throw + It 'Should have removed the team' { + { Get-GitHubTeam -OrganizationName $organizationName -TeamName $teamName } | + Should -Throw + } } } } From e5f8ecc9f68cfdac28bbc9717280e7bfd3a08316 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sun, 19 Jul 2020 11:51:02 +0100 Subject: [PATCH 19/25] Add delays to failing tests --- Tests/GitHubTeams.tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index f8da6b13..62d522f5 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -250,6 +250,10 @@ try AfterAll { if (Get-Variable -Name team -ErrorAction SilentlyContinue) { + # The CI build has been unreliable with this test. + # Adding a short sleep to ensure successive queries reflect updated state. + Start-Sleep -Seconds $script:defaultSleepSecondsForReliability + $team | Remove-GitHubTeam -Force } } @@ -585,6 +589,10 @@ try Privacy = $privacy } + # The CI build has been unreliable with this test. + # Adding a short sleep to ensure successive queries reflect updated state. + Start-Sleep -Seconds $script:defaultSleepSecondsForReliability + $updatedTeam = Set-GitHubTeam @updateGitHubTeamParms } @@ -661,6 +669,10 @@ try $teamName = [Guid]::NewGuid().Guid $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + + # The CI build has been unreliable with this test. + # Adding a short sleep to ensure successive queries reflect updated state. + Start-Sleep -Seconds $script:defaultSleepSecondsForReliability } It 'Should not throw an exception' { From 02db1664228687ba5f3ac2a40e3540edece60472 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sun, 19 Jul 2020 23:48:04 +0100 Subject: [PATCH 20/25] Update tests --- Tests/Common.ps1 | 2 +- Tests/GitHubTeams.tests.ps1 | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Tests/Common.ps1 b/Tests/Common.ps1 index d7ced214..fdabef7b 100644 --- a/Tests/Common.ps1 +++ b/Tests/Common.ps1 @@ -104,7 +104,7 @@ function Initialize-CommonTestSetup # We execute so many successive state changing commands on the same object that sometimes # GitHub gets confused. We'll add an intentional delay to slow down our execution in an effort # to increase the reliability of the tests. - Set-GitHubConfiguration -StateChangeDelaySeconds 3 + Set-GitHubConfiguration -StateChangeDelaySeconds 1 } Initialize-CommonTestSetup diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index 62d522f5..f8da6b13 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -250,10 +250,6 @@ try AfterAll { if (Get-Variable -Name team -ErrorAction SilentlyContinue) { - # The CI build has been unreliable with this test. - # Adding a short sleep to ensure successive queries reflect updated state. - Start-Sleep -Seconds $script:defaultSleepSecondsForReliability - $team | Remove-GitHubTeam -Force } } @@ -589,10 +585,6 @@ try Privacy = $privacy } - # The CI build has been unreliable with this test. - # Adding a short sleep to ensure successive queries reflect updated state. - Start-Sleep -Seconds $script:defaultSleepSecondsForReliability - $updatedTeam = Set-GitHubTeam @updateGitHubTeamParms } @@ -669,10 +661,6 @@ try $teamName = [Guid]::NewGuid().Guid $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName - - # The CI build has been unreliable with this test. - # Adding a short sleep to ensure successive queries reflect updated state. - Start-Sleep -Seconds $script:defaultSleepSecondsForReliability } It 'Should not throw an exception' { From 9d8d8fa290128ba0662826fcc68162762d1683d2 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Tue, 21 Jul 2020 17:48:58 +0100 Subject: [PATCH 21/25] Restore StateChangeDelaySeconds to 3 --- Tests/Common.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Common.ps1 b/Tests/Common.ps1 index fdabef7b..d7ced214 100644 --- a/Tests/Common.ps1 +++ b/Tests/Common.ps1 @@ -104,7 +104,7 @@ function Initialize-CommonTestSetup # We execute so many successive state changing commands on the same object that sometimes # GitHub gets confused. We'll add an intentional delay to slow down our execution in an effort # to increase the reliability of the tests. - Set-GitHubConfiguration -StateChangeDelaySeconds 1 + Set-GitHubConfiguration -StateChangeDelaySeconds 3 } Initialize-CommonTestSetup From 1185492299e60d4cf8ffb8fe6985dbcd7227d4bf Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Sat, 1 Aug 2020 15:46:34 +0100 Subject: [PATCH 22/25] Standardise ShouldProcess --- GitHubTeams.ps1 | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 0c9ed2e6..7fe23a68 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -388,9 +388,6 @@ function New-GitHubTeam 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.')] @@ -498,6 +495,11 @@ function New-GitHubTeam $hashBody['parent_team_id'] = $team.id } + if (-not $PSCmdlet.ShouldProcess($TeamName, 'Create GitHub Team')) + { + return + } + $params = @{ UriFragment = $uriFragment Body = (ConvertTo-Json -InputObject $hashBody) @@ -568,9 +570,6 @@ filter Set-GitHubTeam 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.')] @@ -647,6 +646,11 @@ filter Set-GitHubTeam $hashBody['parent_team_id'] = $parentTeam.id } + if (-not $PSCmdlet.ShouldProcess($TeamName, 'Set GitHub Team')) + { + return + } + $params = @{ UriFragment = $uriFragment Body = (ConvertTo-Json -InputObject $hashBody) @@ -715,9 +719,6 @@ filter Remove-GitHubTeam 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.')] @@ -781,23 +782,25 @@ filter Remove-GitHubTeam $ConfirmPreference = 'None' } - if ($PSCmdlet.ShouldProcess($TeamName, "Remove Team")) + if (-not $PSCmdlet.ShouldProcess($TeamName, 'Remove Github Team')) { - Write-InvocationLog + return + } - $params = @{ - UriFragment = $uriFragment - Method = 'Delete' - Description = "Deleting $TeamName" - AccessToken = $AccessToken - TelemetryEventName = $MyInvocation.MyCommand.Name - TelemetryProperties = $telemetryProperties - NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` - -Name NoStatus -ConfigValueName DefaultNoStatus) - } + Write-InvocationLog - Invoke-GHRestMethod @params | Out-Null + $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 From 92d24254db0749be541e1ee69f717da45044d6fc Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Wed, 5 Aug 2020 08:08:55 +0100 Subject: [PATCH 23/25] Remove unneeded Whatif/Confirm parms --- GitHubTeams.ps1 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 7fe23a68..64a95836 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -478,8 +478,6 @@ function New-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName TeamName = $ParentTeamName - Whatif = $false - Confirm = $false } if ($PSBoundParameters.ContainsKey('AccessToken')) { @@ -615,8 +613,6 @@ filter Set-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName - Whatif = $false - Confirm = $false } if ($PSBoundParameters.ContainsKey('AccessToken')) { @@ -761,8 +757,6 @@ filter Remove-GitHubTeam $getGitHubTeamParms = @{ OrganizationName = $OrganizationName TeamName = $TeamName - Whatif = $false - Confirm = $false } if ($PSBoundParameters.ContainsKey('AccessToken')) { From 4275e716fdee54f25f9c1f908b2226ba0e781679 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Tue, 11 Aug 2020 07:53:57 +0100 Subject: [PATCH 24/25] Fix Remove-GitHubTeam test --- Tests/GitHubTeams.tests.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index f8da6b13..01933161 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -685,15 +685,15 @@ try $description = 'Team Description' $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } - It 'Should not throw an exception' { - { $team |Remove-GitHubTeam -Force } | Should -Not -Throw - } + It 'Should not throw an exception' { + { $team |Remove-GitHubTeam -Force } | Should -Not -Throw + } - It 'Should have removed the team' { - { Get-GitHubTeam -OrganizationName $organizationName -TeamName $teamName } | - Should -Throw - } + It 'Should have removed the team' { + { Get-GitHubTeam -OrganizationName $organizationName -TeamName $teamName } | + Should -Throw } } } From 96f056e2c4115dbc527d04d4d48af305728445f2 Mon Sep 17 00:00:00 2001 From: Simon Heather Date: Tue, 11 Aug 2020 20:14:14 +0100 Subject: [PATCH 25/25] Fix review comments --- GitHubTeams.ps1 | 6 +++--- Tests/GitHubTeams.tests.ps1 | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 64a95836..55d1e31a 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -749,6 +749,8 @@ filter Remove-GitHubTeam [switch] $NoStatus ) + Write-InvocationLog + $telemetryProperties = @{ OrganizationName = (Get-PiiSafeString -PlainText $RepositoryName) TeamName = (Get-PiiSafeString -PlainText $TeamName) @@ -781,8 +783,6 @@ filter Remove-GitHubTeam return } - Write-InvocationLog - $params = @{ UriFragment = $uriFragment Method = 'Delete' @@ -853,7 +853,7 @@ filter Add-GitHubTeamAdditionalProperties } } - Add-Member -InputObject $item -Name 'OrganizationName' -value $organizationName -MemberType NoteProperty -Force + 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/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index 01933161..7d312e37 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -15,8 +15,6 @@ param() $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent . (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1') -Set-StrictMode -Version 1.0 - try { # Define Script-scoped, readonly, hidden variables.