From 1d9d11ef415bb990bf60200e9828540c42f1f17c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 08:10:52 +0000 Subject: [PATCH 1/2] Initial plan From 7ca3908d92c5491d41f32e09d59d5bb66b91fe8c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 08:15:30 +0000 Subject: [PATCH 2/2] Add label management classes and functions Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> --- src/classes/public/Issues/GitHubLabel.ps1 | 47 ++++++++ src/formats/GitHubLabel.Format.ps1xml | 51 +++++++++ .../Issues/Labels/Get-GitHubLabelByName.ps1 | 70 ++++++++++++ .../Issues/Labels/Get-GitHubLabelList.ps1 | 71 ++++++++++++ .../Issues/Labels/Add-GitHubIssueLabel.ps1 | 81 ++++++++++++++ .../Issues/Labels/Get-GitHubIssueLabel.ps1 | 80 ++++++++++++++ .../public/Issues/Labels/Get-GitHubLabel.ps1 | 78 +++++++++++++ .../Labels/Get-GitHubMilestoneLabel.ps1 | 80 ++++++++++++++ .../public/Issues/Labels/New-GitHubLabel.ps1 | 90 +++++++++++++++ .../Issues/Labels/Remove-GitHubIssueLabel.ps1 | 98 +++++++++++++++++ .../Issues/Labels/Remove-GitHubLabel.ps1 | 70 ++++++++++++ .../Issues/Labels/Set-GitHubIssueLabel.ps1 | 88 +++++++++++++++ .../public/Issues/Labels/Set-GitHubLabel.ps1 | 104 ++++++++++++++++++ src/types/GitHubLabel.Types.ps1xml | 12 ++ 14 files changed, 1020 insertions(+) create mode 100644 src/classes/public/Issues/GitHubLabel.ps1 create mode 100644 src/formats/GitHubLabel.Format.ps1xml create mode 100644 src/functions/private/Issues/Labels/Get-GitHubLabelByName.ps1 create mode 100644 src/functions/private/Issues/Labels/Get-GitHubLabelList.ps1 create mode 100644 src/functions/public/Issues/Labels/Add-GitHubIssueLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/Get-GitHubIssueLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/Get-GitHubLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/Get-GitHubMilestoneLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/New-GitHubLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/Remove-GitHubIssueLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/Remove-GitHubLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/Set-GitHubIssueLabel.ps1 create mode 100644 src/functions/public/Issues/Labels/Set-GitHubLabel.ps1 create mode 100644 src/types/GitHubLabel.Types.ps1xml diff --git a/src/classes/public/Issues/GitHubLabel.ps1 b/src/classes/public/Issues/GitHubLabel.ps1 new file mode 100644 index 000000000..8ef23805b --- /dev/null +++ b/src/classes/public/Issues/GitHubLabel.ps1 @@ -0,0 +1,47 @@ +class GitHubLabel : GitHubNode { + # The name of the label + # Example: "bug" + [string] $Name + + # The repository where the label is + [string] $Repository + + # The owner of the repository + [string] $Owner + + # The description of the label + # Example: "Something isn't working" + [string] $Description + + # The color of the label (hex code without #) + # Example: "d73a4a" + [string] $Color + + # Whether this is a default label + # Example: true + [bool] $IsDefault + + # The API URL of the label + # Example: "https://api.github.com/repos/octocat/Hello-World/labels/bug" + [string] $Url + + # Constructor from API response + GitHubLabel( + [object] $data + ) { + $this.ID = $data.id + $this.NodeID = $data.node_id + $this.Name = $data.name + $this.Description = $data.description + $this.Color = $data.color + $this.IsDefault = $data.default + $this.Url = $data.url + + # Parse owner and repository from URL + # URL format: https://api.github.com/repos/{owner}/{repo}/labels/{name} + if ($data.url -match 'repos/([^/]+)/([^/]+)/labels') { + $this.Owner = $matches[1] + $this.Repository = $matches[2] + } + } +} diff --git a/src/formats/GitHubLabel.Format.ps1xml b/src/formats/GitHubLabel.Format.ps1xml new file mode 100644 index 000000000..3f5bf9536 --- /dev/null +++ b/src/formats/GitHubLabel.Format.ps1xml @@ -0,0 +1,51 @@ + + + + + GitHubLabelTable + + GitHubLabel + + + + + + + + + + + + + + + + + + + + + + if ($Host.UI.SupportsVirtualTerminal) { + $PSStyle.FormatHyperlink($_.Name, $_.Url) + } else { + $_.Name + } + + + + Description + + + Color + + + IsDefault + + + + + + + + diff --git a/src/functions/private/Issues/Labels/Get-GitHubLabelByName.ps1 b/src/functions/private/Issues/Labels/Get-GitHubLabelByName.ps1 new file mode 100644 index 000000000..b7a6e3568 --- /dev/null +++ b/src/functions/private/Issues/Labels/Get-GitHubLabelByName.ps1 @@ -0,0 +1,70 @@ +filter Get-GitHubLabelByName { + <# + .SYNOPSIS + Get a label + + .DESCRIPTION + Gets a label by name. + + .EXAMPLE + Get-GitHubLabelByName -Owner 'octocat' -Repository 'hello-world' -Name 'bug' -Context $context + + Gets the label with the name 'bug' for the repository 'hello-world' owned by 'octocat'. + + .INPUTS + None + + .OUTPUTS + GitHubLabel + + .NOTES + [Get a label](https://docs.github.com/rest/issues/labels#get-a-label) + #> + [OutputType([GitHubLabel])] + [CmdletBinding()] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Repository, + + # The name of the label. + [Parameter(Mandatory)] + [string] $Name, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter(Mandatory)] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $apiParams = @{ + Method = 'GET' + APIEndpoint = "/repos/$Owner/$Repository/labels/$([uri]::EscapeDataString($Name))" + Context = $Context + } + + try { + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } catch { + Write-Error $_.Exception.Message + return + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/private/Issues/Labels/Get-GitHubLabelList.ps1 b/src/functions/private/Issues/Labels/Get-GitHubLabelList.ps1 new file mode 100644 index 000000000..d7358a1b9 --- /dev/null +++ b/src/functions/private/Issues/Labels/Get-GitHubLabelList.ps1 @@ -0,0 +1,71 @@ +filter Get-GitHubLabelList { + <# + .SYNOPSIS + List labels for a repository + + .DESCRIPTION + Lists all labels for a repository. + + .EXAMPLE + Get-GitHubLabelList -Owner 'octocat' -Repository 'hello-world' -Context $context + + Lists all labels for the repository 'hello-world' owned by 'octocat'. + + .INPUTS + None + + .OUTPUTS + GitHubLabel + + .NOTES + [List labels for a repository](https://docs.github.com/rest/issues/labels#list-labels-for-a-repository) + #> + [OutputType([GitHubLabel])] + [CmdletBinding()] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Repository, + + # The number of results per page (max 100). + [Parameter()] + [System.Nullable[int]] $PerPage, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter(Mandatory)] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $apiParams = @{ + Method = 'GET' + APIEndpoint = "/repos/$Owner/$Repository/labels" + Context = $Context + } + + if ($PerPage) { + $apiParams['QueryParameters'] = @{ + per_page = $PerPage + } + } + + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Add-GitHubIssueLabel.ps1 b/src/functions/public/Issues/Labels/Add-GitHubIssueLabel.ps1 new file mode 100644 index 000000000..1b2ee6b9d --- /dev/null +++ b/src/functions/public/Issues/Labels/Add-GitHubIssueLabel.ps1 @@ -0,0 +1,81 @@ +filter Add-GitHubIssueLabel { + <# + .SYNOPSIS + Add labels to an issue + + .DESCRIPTION + Adds labels to an issue. + + .EXAMPLE + Add-GitHubIssueLabel -Owner 'octocat' -Repository 'hello-world' -IssueNumber 1 -Label 'bug', 'enhancement' + + Adds the labels 'bug' and 'enhancement' to issue #1 in the repository 'hello-world' owned by 'octocat'. + + .INPUTS + None + + .OUTPUTS + GitHubLabel + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Add-GitHubIssueLabel/ + + .NOTES + [Add labels to an issue](https://docs.github.com/rest/issues/labels#add-labels-to-an-issue) + #> + [OutputType([GitHubLabel])] + [CmdletBinding(SupportsShouldProcess)] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The number that identifies the issue. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [int] $IssueNumber, + + # The names of the labels to add to the issue. + [Parameter(Mandatory)] + [string[]] $Label, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + if ($PSCmdlet.ShouldProcess("Issue #$IssueNumber in repository '$Owner/$Repository'", "Add labels: $($Label -join ', ')")) { + $body = @{ + labels = $Label + } + + $apiParams = @{ + Method = 'POST' + APIEndpoint = "/repos/$Owner/$Repository/issues/$IssueNumber/labels" + Body = $body + Context = $Context + } + + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Get-GitHubIssueLabel.ps1 b/src/functions/public/Issues/Labels/Get-GitHubIssueLabel.ps1 new file mode 100644 index 000000000..3c8bd8d3a --- /dev/null +++ b/src/functions/public/Issues/Labels/Get-GitHubIssueLabel.ps1 @@ -0,0 +1,80 @@ +filter Get-GitHubIssueLabel { + <# + .SYNOPSIS + Get labels for an issue + + .DESCRIPTION + Lists all labels for an issue. + + .EXAMPLE + Get-GitHubIssueLabel -Owner 'octocat' -Repository 'hello-world' -IssueNumber 1 + + Lists all labels for issue #1 in the repository 'hello-world' owned by 'octocat'. + + .INPUTS + None + + .OUTPUTS + GitHubLabel + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Get-GitHubIssueLabel/ + + .NOTES + [List labels for an issue](https://docs.github.com/rest/issues/labels#list-labels-for-an-issue) + #> + [OutputType([GitHubLabel])] + [CmdletBinding()] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The number that identifies the issue. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [int] $IssueNumber, + + # The number of results per page (max 100). + [Parameter()] + [System.Nullable[int]] $PerPage, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $apiParams = @{ + Method = 'GET' + APIEndpoint = "/repos/$Owner/$Repository/issues/$IssueNumber/labels" + Context = $Context + } + + if ($PerPage) { + $apiParams['QueryParameters'] = @{ + per_page = $PerPage + } + } + + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Get-GitHubLabel.ps1 b/src/functions/public/Issues/Labels/Get-GitHubLabel.ps1 new file mode 100644 index 000000000..4691fa253 --- /dev/null +++ b/src/functions/public/Issues/Labels/Get-GitHubLabel.ps1 @@ -0,0 +1,78 @@ +filter Get-GitHubLabel { + <# + .SYNOPSIS + Get labels for a repository + + .DESCRIPTION + Lists all labels for a repository or gets a single label by name. + + .EXAMPLE + Get-GitHubLabel -Owner 'octocat' -Repository 'hello-world' + + Lists all labels for the repository 'hello-world' owned by 'octocat'. + + .EXAMPLE + Get-GitHubLabel -Owner 'octocat' -Repository 'hello-world' -Name 'bug' + + Gets the label with the name 'bug' for the repository 'hello-world' owned by 'octocat'. + + .INPUTS + GitHubRepository + + .OUTPUTS + GitHubLabel + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Get-GitHubLabel/ + #> + [OutputType([GitHubLabel])] + [CmdletBinding()] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The name of the label to get. If not specified, all labels will be listed. + [Parameter()] + [string] $Name, + + # The number of results per page (max 100). + [Parameter()] + [System.Nullable[int]] $PerPage, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $params = @{ + Owner = $Owner + Repository = $Repository + Context = $Context + } + + if ($Name) { + Get-GitHubLabelByName @params -Name $Name + } else { + Get-GitHubLabelList @params -PerPage $PerPage + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Get-GitHubMilestoneLabel.ps1 b/src/functions/public/Issues/Labels/Get-GitHubMilestoneLabel.ps1 new file mode 100644 index 000000000..04a2b241a --- /dev/null +++ b/src/functions/public/Issues/Labels/Get-GitHubMilestoneLabel.ps1 @@ -0,0 +1,80 @@ +filter Get-GitHubMilestoneLabel { + <# + .SYNOPSIS + Get labels for issues in a milestone + + .DESCRIPTION + Lists labels for every issue in a milestone. + + .EXAMPLE + Get-GitHubMilestoneLabel -Owner 'octocat' -Repository 'hello-world' -MilestoneNumber 1 + + Lists all labels for issues in milestone #1 in the repository 'hello-world' owned by 'octocat'. + + .INPUTS + None + + .OUTPUTS + GitHubLabel + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Get-GitHubMilestoneLabel/ + + .NOTES + [List labels for issues in a milestone](https://docs.github.com/rest/issues/labels#list-labels-for-issues-in-a-milestone) + #> + [OutputType([GitHubLabel])] + [CmdletBinding()] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The number that identifies the milestone. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [int] $MilestoneNumber, + + # The number of results per page (max 100). + [Parameter()] + [System.Nullable[int]] $PerPage, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $apiParams = @{ + Method = 'GET' + APIEndpoint = "/repos/$Owner/$Repository/milestones/$MilestoneNumber/labels" + Context = $Context + } + + if ($PerPage) { + $apiParams['QueryParameters'] = @{ + per_page = $PerPage + } + } + + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/New-GitHubLabel.ps1 b/src/functions/public/Issues/Labels/New-GitHubLabel.ps1 new file mode 100644 index 000000000..5737cf0c0 --- /dev/null +++ b/src/functions/public/Issues/Labels/New-GitHubLabel.ps1 @@ -0,0 +1,90 @@ +filter New-GitHubLabel { + <# + .SYNOPSIS + Create a label + + .DESCRIPTION + Creates a label for a repository. + + .EXAMPLE + New-GitHubLabel -Owner 'octocat' -Repository 'hello-world' -Name 'bug' -Color 'd73a4a' -Description 'Something is not working' + + Creates a label with the name 'bug' for the repository 'hello-world' owned by 'octocat'. + + .INPUTS + GitHubRepository + + .OUTPUTS + GitHubLabel + + .LINK + https://psmodule.io/GitHub/Functions/Issues/New-GitHubLabel/ + + .NOTES + [Create a label](https://docs.github.com/rest/issues/labels#create-a-label) + #> + [OutputType([GitHubLabel])] + [CmdletBinding(SupportsShouldProcess)] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The name of the label. + [Parameter(Mandatory)] + [string] $Name, + + # The color of the label (hex code without #). Example: 'd73a4a' + [Parameter(Mandatory)] + [string] $Color, + + # A short description of the label. + [Parameter()] + [string] $Description, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + if ($PSCmdlet.ShouldProcess("Label '$Name' in repository '$Owner/$Repository'", 'Create')) { + $body = @{ + name = $Name + color = $Color -replace '^#', '' + } + + if ($PSBoundParameters.ContainsKey('Description')) { + $body['description'] = $Description + } + + $apiParams = @{ + Method = 'POST' + APIEndpoint = "/repos/$Owner/$Repository/labels" + Body = $body + Context = $Context + } + + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Remove-GitHubIssueLabel.ps1 b/src/functions/public/Issues/Labels/Remove-GitHubIssueLabel.ps1 new file mode 100644 index 000000000..48a002236 --- /dev/null +++ b/src/functions/public/Issues/Labels/Remove-GitHubIssueLabel.ps1 @@ -0,0 +1,98 @@ +filter Remove-GitHubIssueLabel { + <# + .SYNOPSIS + Remove labels from an issue + + .DESCRIPTION + Removes a label from an issue or all labels if no label name is specified. + + .EXAMPLE + Remove-GitHubIssueLabel -Owner 'octocat' -Repository 'hello-world' -IssueNumber 1 -Name 'bug' + + Removes the label 'bug' from issue #1 in the repository 'hello-world' owned by 'octocat'. + + .EXAMPLE + Remove-GitHubIssueLabel -Owner 'octocat' -Repository 'hello-world' -IssueNumber 1 + + Removes all labels from issue #1 in the repository 'hello-world' owned by 'octocat'. + + .INPUTS + None + + .OUTPUTS + None + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Remove-GitHubIssueLabel/ + + .NOTES + [Remove a label from an issue](https://docs.github.com/rest/issues/labels#remove-a-label-from-an-issue) + [Remove all labels from an issue](https://docs.github.com/rest/issues/labels#remove-all-labels-from-an-issue) + #> + [OutputType([void])] + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'RemoveOne')] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The number that identifies the issue. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [int] $IssueNumber, + + # The name of the label to remove. If not specified, all labels will be removed. + [Parameter(ParameterSetName = 'RemoveOne')] + [string] $Name, + + # Remove all labels from the issue. + [Parameter(Mandatory, ParameterSetName = 'RemoveAll')] + [switch] $All, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $target = if ($All -or -not $Name) { + "all labels from issue #$IssueNumber" + } else { + "label '$Name' from issue #$IssueNumber" + } + + if ($PSCmdlet.ShouldProcess("Repository '$Owner/$Repository'", "Remove $target")) { + if ($All -or -not $Name) { + $apiParams = @{ + Method = 'DELETE' + APIEndpoint = "/repos/$Owner/$Repository/issues/$IssueNumber/labels" + Context = $Context + } + } else { + $apiParams = @{ + Method = 'DELETE' + APIEndpoint = "/repos/$Owner/$Repository/issues/$IssueNumber/labels/$([uri]::EscapeDataString($Name))" + Context = $Context + } + } + + Invoke-GitHubAPI @apiParams | Out-Null + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Remove-GitHubLabel.ps1 b/src/functions/public/Issues/Labels/Remove-GitHubLabel.ps1 new file mode 100644 index 000000000..9fddc95fc --- /dev/null +++ b/src/functions/public/Issues/Labels/Remove-GitHubLabel.ps1 @@ -0,0 +1,70 @@ +filter Remove-GitHubLabel { + <# + .SYNOPSIS + Delete a label + + .DESCRIPTION + Deletes a label from a repository. + + .EXAMPLE + Remove-GitHubLabel -Owner 'octocat' -Repository 'hello-world' -Name 'bug' + + Deletes the label with the name 'bug' from the repository 'hello-world' owned by 'octocat'. + + .INPUTS + GitHubLabel + + .OUTPUTS + None + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Remove-GitHubLabel/ + + .NOTES + [Delete a label](https://docs.github.com/rest/issues/labels#delete-a-label) + #> + [OutputType([void])] + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The name of the label to delete. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Name, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + if ($PSCmdlet.ShouldProcess("Label '$Name' in repository '$Owner/$Repository'", 'Delete')) { + $apiParams = @{ + Method = 'DELETE' + APIEndpoint = "/repos/$Owner/$Repository/labels/$([uri]::EscapeDataString($Name))" + Context = $Context + } + + Invoke-GitHubAPI @apiParams | Out-Null + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Set-GitHubIssueLabel.ps1 b/src/functions/public/Issues/Labels/Set-GitHubIssueLabel.ps1 new file mode 100644 index 000000000..fc749cd45 --- /dev/null +++ b/src/functions/public/Issues/Labels/Set-GitHubIssueLabel.ps1 @@ -0,0 +1,88 @@ +filter Set-GitHubIssueLabel { + <# + .SYNOPSIS + Set labels for an issue + + .DESCRIPTION + Replaces all labels on an issue with the specified labels. Removes any labels not included in the Label array. + + .EXAMPLE + Set-GitHubIssueLabel -Owner 'octocat' -Repository 'hello-world' -IssueNumber 1 -Label 'bug', 'documentation' + + Replaces all labels on issue #1 with 'bug' and 'documentation' in the repository 'hello-world' owned by 'octocat'. + + .EXAMPLE + Set-GitHubIssueLabel -Owner 'octocat' -Repository 'hello-world' -IssueNumber 1 -Label @() + + Removes all labels from issue #1 in the repository 'hello-world' owned by 'octocat'. + + .INPUTS + None + + .OUTPUTS + GitHubLabel + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Set-GitHubIssueLabel/ + + .NOTES + [Set labels for an issue](https://docs.github.com/rest/issues/labels#set-labels-for-an-issue) + #> + [OutputType([GitHubLabel])] + [CmdletBinding(SupportsShouldProcess)] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The number that identifies the issue. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [int] $IssueNumber, + + # The names of the labels to set for the issue. Pass an empty array to remove all labels. + [Parameter(Mandatory)] + [AllowEmptyCollection()] + [string[]] $Label, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $labelText = if ($Label.Count -eq 0) { 'none' } else { $Label -join ', ' } + if ($PSCmdlet.ShouldProcess("Issue #$IssueNumber in repository '$Owner/$Repository'", "Set labels to: $labelText")) { + $body = @{ + labels = $Label + } + + $apiParams = @{ + Method = 'PUT' + APIEndpoint = "/repos/$Owner/$Repository/issues/$IssueNumber/labels" + Body = $body + Context = $Context + } + + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/public/Issues/Labels/Set-GitHubLabel.ps1 b/src/functions/public/Issues/Labels/Set-GitHubLabel.ps1 new file mode 100644 index 000000000..26b65e727 --- /dev/null +++ b/src/functions/public/Issues/Labels/Set-GitHubLabel.ps1 @@ -0,0 +1,104 @@ +filter Set-GitHubLabel { + <# + .SYNOPSIS + Update a label + + .DESCRIPTION + Updates a label for a repository. + + .EXAMPLE + Set-GitHubLabel -Owner 'octocat' -Repository 'hello-world' -Name 'bug' -NewName 'defect' + + Renames the label 'bug' to 'defect' for the repository 'hello-world' owned by 'octocat'. + + .EXAMPLE + Set-GitHubLabel -Owner 'octocat' -Repository 'hello-world' -Name 'bug' -Color 'ff0000' -Description 'Critical issue' + + Updates the color and description of the label 'bug' for the repository 'hello-world' owned by 'octocat'. + + .INPUTS + GitHubLabel + + .OUTPUTS + GitHubLabel + + .LINK + https://psmodule.io/GitHub/Functions/Issues/Set-GitHubLabel/ + + .NOTES + [Update a label](https://docs.github.com/rest/issues/labels#update-a-label) + #> + [OutputType([GitHubLabel])] + [CmdletBinding(SupportsShouldProcess)] + param( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [Alias('Organization', 'User')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Repository, + + # The current name of the label. + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string] $Name, + + # The new name of the label. + [Parameter()] + [string] $NewName, + + # The color of the label (hex code without #). Example: 'd73a4a' + [Parameter()] + [string] $Color, + + # A short description of the label. + [Parameter()] + [string] $Description, + + # The context to run the command in. Used to get the details for the API call. + # Can be either a string or a GitHubContext object. + [Parameter()] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + if ($PSCmdlet.ShouldProcess("Label '$Name' in repository '$Owner/$Repository'", 'Update')) { + $body = @{} + + if ($PSBoundParameters.ContainsKey('NewName')) { + $body['new_name'] = $NewName + } + + if ($PSBoundParameters.ContainsKey('Color')) { + $body['color'] = $Color -replace '^#', '' + } + + if ($PSBoundParameters.ContainsKey('Description')) { + $body['description'] = $Description + } + + $apiParams = @{ + Method = 'PATCH' + APIEndpoint = "/repos/$Owner/$Repository/labels/$([uri]::EscapeDataString($Name))" + Body = $body + Context = $Context + } + + Invoke-GitHubAPI @apiParams | ForEach-Object { + [GitHubLabel]::new($_.Response) + } + } + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/types/GitHubLabel.Types.ps1xml b/src/types/GitHubLabel.Types.ps1xml new file mode 100644 index 000000000..4b205b472 --- /dev/null +++ b/src/types/GitHubLabel.Types.ps1xml @@ -0,0 +1,12 @@ + + + + GitHubLabel + + + Label + Name + + + +