From 85170ce517dc4941518d51d788843a87612e25e0 Mon Sep 17 00:00:00 2001 From: Jess Pomfret Date: Tue, 12 May 2020 18:01:53 +0100 Subject: [PATCH] Adding functionality for Project Columns (#162) Covers: - List project columns - Get a project column - Create a project column - Update a project column - Delete a project column - Move a project column --- GitHubProjectColumns.ps1 | 407 +++++++++++++++++++++++++++ PowerShellForGitHub.psd1 | 7 + Tests/GitHubProjectColumns.tests.ps1 | 141 ++++++++++ 3 files changed, 555 insertions(+) create mode 100644 GitHubProjectColumns.ps1 create mode 100644 Tests/GitHubProjectColumns.tests.ps1 diff --git a/GitHubProjectColumns.ps1 b/GitHubProjectColumns.ps1 new file mode 100644 index 00000000..bb178d0c --- /dev/null +++ b/GitHubProjectColumns.ps1 @@ -0,0 +1,407 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +function Get-GitHubProjectColumn +{ +<# + .DESCRIPTION + Get the columns for a given Github Project. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Project + ID of the project to retrieve a list of columns for. + + .PARAMETER Column + ID of the column to retrieve. + + .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 command line 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. + + .EXAMPLE + Get-GitHubProjectColumn -Project 999999 + + Get the columns for project 999999. + + .EXAMPLE + Get-GitHubProjectColumn -Column 999999 + + Get the column with ID 999999. +#> + [CmdletBinding( + SupportsShouldProcess, + DefaultParameterSetName = 'Project')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory, ParameterSetName = 'Project')] + [int64] $Project, + + [Parameter(Mandatory, ParameterSetName = 'Column')] + [int64] $Column, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $telemetryProperties = @{} + + $uriFragment = [String]::Empty + $description = [String]::Empty + + if ($PSCmdlet.ParameterSetName -eq 'Project') + { + $telemetryProperties['Project'] = Get-PiiSafeString -PlainText $Project + + $uriFragment = "/projects/$Project/columns" + $description = "Getting project columns for $Project" + } + elseif ($PSCmdlet.ParameterSetName -eq 'Column') + { + $telemetryProperties['Column'] = Get-PiiSafeString -PlainText $Column + + $uriFragment = "/projects/columns/$Column" + $description = "Getting project column $Column" + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Description' = $description + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + 'AcceptHeader' = 'application/vnd.github.inertia-preview+json' + } + + return Invoke-GHRestMethodMultipleResult @params +} + +function New-GitHubProjectColumn +{ +<# + .DESCRIPTION + Creates a new column for a Github project. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Project + ID of the project to create a column for. + + .PARAMETER Name + The name of the column to create. + + .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 command line 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. + + .EXAMPLE + New-GitHubProjectColumn -Project 999999 -Name 'Done' + + Creates a column called 'Done' for the project with ID 999999. +#> + [CmdletBinding( + SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + + [Parameter(Mandatory)] + [int64] $Project, + + [Parameter(Mandatory)] + [string] $Name, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $telemetryProperties = @{} + $telemetryProperties['Project'] = Get-PiiSafeString -PlainText $Project + + $uriFragment = "/projects/$Project/columns" + $apiDescription = "Creating project column $Name" + + $hashBody = @{ + 'name' = $Name + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Method' = 'Post' + 'Description' = $apiDescription + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + 'AcceptHeader' = 'application/vnd.github.inertia-preview+json' + } + + return Invoke-GHRestMethod @params +} + +function Set-GitHubProjectColumn +{ +<# + .DESCRIPTION + Modify a GitHub Project Column. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Column + ID of the column to modify. + + .PARAMETER Name + The name for the column. + + .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 command line 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. + + .EXAMPLE + Set-GitHubProjectColumn -Column 999999 -Name NewColumnName + + Set the project column name to 'NewColumnName' with column with ID 999999. +#> + [CmdletBinding( + SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [int64] $Column, + + [Parameter(Mandatory)] + [string] $Name, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $telemetryProperties = @{} + + $uriFragment = "/projects/columns/$Column" + $apiDescription = "Updating column $Column" + + $hashBody = @{ + 'name' = $Name + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Description' = $apiDescription + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'AccessToken' = $AccessToken + 'Method' = 'Patch' + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + 'AcceptHeader' = 'application/vnd.github.inertia-preview+json' + } + + return Invoke-GHRestMethod @params +} + +function Remove-GitHubProjectColumn +{ +<# + .DESCRIPTION + Removes the column for a project. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Column + ID of the column to remove. + + .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 command line 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. + + .EXAMPLE + Remove-GitHubProjectColumn -Column 999999 + + Remove project column with ID 999999. + + .EXAMPLE + Remove-GitHubProjectColumn -Column 999999 -Confirm:$False + + Removes the project column with ID 999999 without prompting for confirmation. +#> + [CmdletBinding( + SupportsShouldProcess, + ConfirmImpact = 'High')] + [Alias('Delete-GitHubProjectColumn')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [int64] $Column, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $telemetryProperties = @{} + + $uriFragment = "/projects/columns/$Column" + $description = "Deleting column $Column" + + if ($PSCmdlet.ShouldProcess($Column, "Remove column")) + { + $params = @{ + 'UriFragment' = $uriFragment + 'Description' = $description + 'AccessToken' = $AccessToken + 'Method' = 'Delete' + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + 'AcceptHeader' = 'application/vnd.github.inertia-preview+json' + } + + return Invoke-GHRestMethod @params + } +} + +function Move-GitHubProjectColumn +{ +<# + .DESCRIPTION + Move a GitHub Project Column. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Column + ID of the column to move. + + .PARAMETER First + Moves the column to be the first for the project. + + .PARAMETER Last + Moves the column to be the last for the project. + + .PARAMETER After + Moves the column to the position after the column ID specified. + Must be within the same project. + + .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 command line 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. + + .EXAMPLE + Move-GitHubProjectColumn -Column 999999 -First + + Moves the project column with ID 999999 to the first position. + + .EXAMPLE + Move-GitHubProjectColumn -Column 999999 -Last + + Moves the project column with ID 999999 to the Last position. + + .EXAMPLE + Move-GitHubProjectColumn -Column 999999 -After 888888 + + Moves the project column with ID 999999 to the position after column with ID 888888. +#> + [CmdletBinding( + SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [int64] $Column, + + [switch] $First, + + [switch] $Last, + + [int64] $After, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $telemetryProperties = @{} + + $uriFragment = "/projects/columns/$Column/moves" + $apiDescription = "Updating column $Column" + + if (-not ($First -xor $Last -xor ($After -gt 0))) + { + $message = 'You must use one (and only one) of the parameters First, Last or After.' + Write-Log -Message $message -level Error + throw $message + } + elseif($First) + { + $position = 'first' + } + elseif($Last) + { + $position = 'last' + } + else + { + $position = "after:$After" + } + + $hashBody = @{ + 'position' = $Position + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Description' = $apiDescription + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'AccessToken' = $AccessToken + 'Method' = 'Post' + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + 'AcceptHeader' = 'application/vnd.github.inertia-preview+json' + } + + return Invoke-GHRestMethod @params +} \ No newline at end of file diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 5b1554ee..426b9343 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -33,6 +33,7 @@ 'GitHubMiscellaneous.ps1', 'GitHubOrganizations.ps1', 'GitHubProjects.ps1', + 'GitHubProjectColumns.ps1', 'GitHubPullRequests.ps1', 'GitHubReleases.ps1', 'GitHubRepositories.ps1', @@ -69,6 +70,7 @@ 'Get-GitHubOrganizationMember', 'Get-GitHubPathTraffic', 'Get-GitHubProject', + 'Get-GitHubProjectColumn', 'Get-GitHubPullRequest', 'Get-GitHubRateLimit', 'Get-GitHubReferrerTraffic', @@ -92,12 +94,14 @@ 'Invoke-GHRestMethodMultipleResult', 'Lock-GitHubIssue', 'Move-GitHubRepositoryOwnership', + 'Move-GitHubProjectColumn', 'New-GithubAssignee', 'New-GitHubComment', 'New-GitHubIssue', 'New-GitHubLabel', 'New-GitHubMilestone', 'New-GitHubProject', + 'New-GitHubProjectColumn', 'New-GitHubPullRequest', 'New-GitHubRepository', 'New-GitHubRepositoryFork', @@ -107,6 +111,7 @@ 'Remove-GitHubLabel', 'Remove-GitHubMilestone', 'Remove-GitHubProject', + 'Remove-GitHubProjectColumn', 'Remove-GitHubRepository', 'Rename-GitHubRepository', 'Reset-GitHubConfiguration', @@ -118,6 +123,7 @@ 'Set-GitHubLabel', 'Set-GitHubMilestone', 'Set-GitHubProject', + 'Set-GitHubProjectColumn', 'Set-GitHubRepositoryTopic', 'Split-GitHubUri', 'Test-GitHubAssignee', @@ -135,6 +141,7 @@ 'Delete-GitHubLabel', 'Delete-GitHubMilestone', 'Delete-GitHubProject', + 'Delete-GitHubProjectColumn' 'Delete-GitHubRepository', 'Get-GitHubBranch', 'Transfer-GitHubRepositoryOwnership' diff --git a/Tests/GitHubProjectColumns.tests.ps1 b/Tests/GitHubProjectColumns.tests.ps1 new file mode 100644 index 00000000..7ba99041 --- /dev/null +++ b/Tests/GitHubProjectColumns.tests.ps1 @@ -0,0 +1,141 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +<# +.Synopsis + Tests for GitHubProjectColumns.ps1 module +#> + +# 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 +{ + # Define Script-scoped, readOnly, hidden variables. + @{ + defaultProject = "TestProject_$([Guid]::NewGuid().Guid)" + defaultColumn = "TestColumn" + defaultColumnTwo = "TestColumnTwo" + defaultColumnUpdate = "TestColumn_Updated" + }.GetEnumerator() | ForEach-Object { + Set-Variable -Force -Scope Script -Option ReadOnly -Visibility Private -Name $_.Key -Value $_.Value + } + + $project = New-GitHubProject -UserProject -Name $defaultProject + + Describe 'Getting Project Columns' { + BeforeAll { + $column = New-GitHubProjectColumn -Project $project.id -Name $defaultColumn + } + AfterAll { + $null = Remove-GitHubProjectColumn -Column $column.id -Confirm:$false + } + + Context 'Get columns for a project' { + $results = Get-GitHubProjectColumn -Project $project.id + It 'Should get column' { + $results | Should Not BeNullOrEmpty + } + + It 'Name is correct' { + $results.name | Should be $defaultColumn + } + } + } + + Describe 'Modify Project Column' { + BeforeAll { + $column = New-GitHubProjectColumn -Project $project.id -Name $defaultColumn + $columntwo = New-GitHubProjectColumn -Project $project.id -Name $defaultColumnTwo + } + AfterAll { + $null = Remove-GitHubProjectColumn -Column $column.id -Confirm:$false + $null = Remove-GitHubProjectColumn -Column $columntwo.id -Confirm:$false + } + + Context 'Modify column name' { + $null = Set-GitHubProjectColumn -Column $column.id -Name $defaultColumnUpdate + $results = Get-GitHubProjectColumn -Column $column.id + + It 'Should get column' { + $results | Should Not BeNullOrEmpty + } + + It 'Name has been updated' { + $results.name | Should be $defaultColumnUpdate + } + } + + Context 'Move column to first position' { + $null = Move-GitHubProjectColumn -Column $columntwo.id -First + $results = Get-GitHubProjectColumn -Project $project.id + + It 'Column is now in the first position' { + $results[0].name | Should be $defaultColumnTwo + } + } + + Context 'Move column using after parameter' { + $null = Move-GitHubProjectColumn -Column $columntwo.id -After $column.id + $results = Get-GitHubProjectColumn -Project $project.id + + It 'Column is now not in the first position' { + $results[1].name | Should be $defaultColumnTwo + } + } + + Context 'Move command throws appropriate error' { + It 'Expected error returned' { + { Move-GitHubProjectColumn -Column $column.id -First -Last } | Should Throw 'You must use one (and only one) of the parameters First, Last or After.' + } + } + } + + Describe 'Create Project Column' { + Context 'Create project column' { + BeforeAll { + $column = @{id = 0} + } + AfterAll { + $null = Remove-GitHubProjectColumn -Column $column.id -Confirm:$false + Remove-Variable -Name column + } + + $column.id = (New-GitHubProjectColumn -Project $project.id -Name $defaultColumn).id + $results = Get-GitHubProjectColumn -Column $column.id + + It 'Column exists' { + $results | Should Not BeNullOrEmpty + } + + It 'Name is correct' { + $results.name | Should be $defaultColumn + } + } + } + + Describe 'Remove project column' { + Context 'Remove project column' { + BeforeAll { + $column = New-GitHubProjectColumn -Project $project.id -Name $defaultColumn + } + + $null = Remove-GitHubProjectColumn -Column $column.id -Confirm:$false + It 'Project column should be removed' { + {Get-GitHubProjectColumn -Column $column.id} | Should Throw + } + } + } + + Remove-GitHubProject -Project $project.id -Confirm:$false +} +finally +{ + if (Test-Path -Path $script:originalConfigFile -PathType Leaf) + { + # Restore the user's configuration to its pre-test state + Restore-GitHubConfiguration -Path $script:originalConfigFile + $script:originalConfigFile = $null + } +} \ No newline at end of file