Skip to content

Add label management functionality #549

@MariusStorhaug

Description

Context

GitHub repositories use labels to categorize issues and pull requests. Labels are essential for workflow automation, issue triage, and project organization. Organization administrators and automation scripts frequently need to create, update, and manage labels across repositories programmatically.

Request

The GitHub PowerShell module currently has no label-related functions, classes, or types. There is no way to manage repository labels, issue labels, or milestone labels through the module.

Desired capability

Users should be able to perform full CRUD operations on repository labels and manage label associations on issues (including pull requests, since they share the issues API). This includes creating, reading, updating, and deleting labels on repositories, and adding, replacing, or removing labels on individual issues.

REST API endpoints

The following REST API endpoints for labels are involved:

Method Endpoint Description
GET /repos/{owner}/{repo}/labels List labels for a repository
GET /repos/{owner}/{repo}/labels/{name} Get a label
POST /repos/{owner}/{repo}/labels Create a label
PATCH /repos/{owner}/{repo}/labels/{name} Update a label
DELETE /repos/{owner}/{repo}/labels/{name} Delete a label
GET /repos/{owner}/{repo}/issues/{issue_number}/labels List labels for an issue
POST /repos/{owner}/{repo}/issues/{issue_number}/labels Add labels to an issue
PUT /repos/{owner}/{repo}/issues/{issue_number}/labels Set labels for an issue
DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name} Remove a label from an issue
DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels Remove all labels from an issue
GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels List labels for issues in a milestone

Label object properties

Property Type Description
id integer Label database ID
node_id string Node ID
url string API URL
name string Label name
description string Label description
color string Hex color code (without #)
default boolean Whether this is a default label

Acceptance criteria

  • Repository labels can be listed, retrieved by name, created, updated, and deleted
  • Issue labels can be listed, added, replaced (set), and removed (individually and all at once)
  • Milestone labels can be listed
  • All commands follow module conventions (Verb-GitHubNoun, pipeline support, context resolution, typed output)
  • GitHubLabel class output with proper formatting
  • Tab completion for label names

Technical decisions

Public function design: Consolidate getters into Get-GitHubLabel with parameter sets (following the Get-GitHubTeam pattern), keep issue label operations as separate public functions since they operate on a different resource relationship (issue-label association vs repo-label CRUD):

Public function Parameter sets Description
Get-GitHubLabel 'List labels for a repository' (default), 'Get a label', 'List labels for an issue', 'List labels for issues in a milestone' Consolidated getter
New-GitHubLabel Single Create a repo label
Update-GitHubLabel Single Update a repo label
Set-GitHubLabel Single Upsert a repo label (Get → New or Update)
Remove-GitHubLabel Single Delete a repo label (ConfirmImpact = 'High')
Add-GitHubIssueLabel Single Add labels to an issue
Set-GitHubIssueLabel Single Replace all labels on an issue
Remove-GitHubIssueLabel 'Remove a label from an issue', 'Remove all labels from an issue' Remove one or all labels

Parameter naming: The -Issue parameter uses aliases -PullRequest and -PR since every PR is an issue in GitHub's API. This follows module conventions.

Separation of repo vs issue label operations: Add-GitHubIssueLabel, Set-GitHubIssueLabel, and Remove-GitHubIssueLabel remain separate because they manage an association (issue ↔ label) rather than the label resource itself. This follows the Add-GitHubReleaseAsset / Add-GitHubSecretSelectedRepository pattern.

Private functions (one per API endpoint):

Private function API endpoint
Get-GitHubLabelListByRepo GET /repos/{o}/{r}/labels
Get-GitHubLabelByName GET /repos/{o}/{r}/labels/{name}
Get-GitHubLabelListByIssue GET /repos/{o}/{r}/issues/{n}/labels
Get-GitHubLabelListByMilestone GET /repos/{o}/{r}/milestones/{n}/labels
New-GitHubLabelOnRepository POST /repos/{o}/{r}/labels
Update-GitHubLabelOnRepository PATCH /repos/{o}/{r}/labels/{name}
Remove-GitHubLabelFromRepository DELETE /repos/{o}/{r}/labels/{name}
Add-GitHubLabelToIssue POST /repos/{o}/{r}/issues/{n}/labels
Set-GitHubLabelOnIssue PUT /repos/{o}/{r}/issues/{n}/labels
Remove-GitHubLabelFromIssue DELETE /repos/{o}/{r}/issues/{n}/labels/{name}
Remove-GitHubLabelFromIssueAll DELETE /repos/{o}/{r}/issues/{n}/labels

Class design: GitHubLabel class extending GitHubNode (provides ID and NodeID). Properties: Name, Description, Color, Default, Url. Types file adds alias LabelName.

File structure:

src/
  classes/public/GitHubLabel.ps1
  formats/GitHubLabel.Format.ps1xml
  types/GitHubLabel.Types.ps1xml
  functions/
    public/Labels/    (8 public functions)
    private/Labels/   (11 private functions)

Test approach: Integration tests covering all label operations per auth case.


Implementation plan

Classes and types

  • Create GitHubLabel class in src/classes/public/GitHubLabel.ps1
  • Create GitHubLabel.Types.ps1xml in src/types/
  • Create GitHubLabel.Format.ps1xml in src/formats/

Private functions

  • Get-GitHubLabelListByRepoGET /repos/{o}/{r}/labels
  • Get-GitHubLabelByNameGET /repos/{o}/{r}/labels/{name}
  • Get-GitHubLabelListByIssueGET /repos/{o}/{r}/issues/{n}/labels
  • Get-GitHubLabelListByMilestoneGET /repos/{o}/{r}/milestones/{n}/labels
  • New-GitHubLabelOnRepositoryPOST /repos/{o}/{r}/labels
  • Update-GitHubLabelOnRepositoryPATCH /repos/{o}/{r}/labels/{name}
  • Remove-GitHubLabelFromRepositoryDELETE /repos/{o}/{r}/labels/{name}
  • Add-GitHubLabelToIssuePOST /repos/{o}/{r}/issues/{n}/labels
  • Set-GitHubLabelOnIssuePUT /repos/{o}/{r}/issues/{n}/labels
  • Remove-GitHubLabelFromIssueDELETE /repos/{o}/{r}/issues/{n}/labels/{name}
  • Remove-GitHubLabelFromIssueAllDELETE /repos/{o}/{r}/issues/{n}/labels

Public functions

  • Get-GitHubLabel — List repo labels / get by name / list by issue / list by milestone
  • New-GitHubLabel — Create a repo label
  • Update-GitHubLabel — Update a repo label
  • Set-GitHubLabel — Upsert a repo label
  • Add-GitHubIssueLabel — Add labels to an issue
  • Set-GitHubIssueLabel — Replace all labels on an issue
  • Remove-GitHubLabel — Delete a repo label
  • Remove-GitHubIssueLabel — Remove a label / all labels from an issue

Completers

  • Add tab-completion for label names

Tests

  • Integration tests for all label functions

Metadata

Metadata

Labels

Projects

Status

Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions