You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The GitHub PowerShell module is used to automate repository management tasks, including workflows that create and manage pull requests. For example, in PSModule/GoogleFonts, an automated workflow updates font data and opens a PR. When a new Auto-Update PR is created, older Auto-Update PRs should be commented on (explaining they are superseded) and then closed.
Currently, no commands exist in the module for interacting with pull requests. The only workaround is shelling out to the gh CLI, which breaks consistency with the rest of the module and loses the typed object pipeline experience.
Request
The module needs commands to list, retrieve, update, and comment on pull requests. Specifically, the following capabilities are missing:
List pull requests — filter by state, head branch, base branch, sort order
Get a specific pull request — retrieve details by PR number
Update a pull request — change title, body, state (open/closed), base branch, or maintainer modification flag
Add a comment to a pull request — post an issue comment on a PR (since pull requests are issues in the GitHub API, this uses the issue comments endpoint)
Pull requests can be listed for a repository with optional filtering by state, head branch, and base branch
A specific pull request can be retrieved by number
A pull request can be closed (or reopened) by updating its state
A comment can be added to a pull request
All returned objects are strongly typed with a GitHubPullRequest class (and GitHubIssueComment class for comments)
Commands integrate with the existing Context resolution pattern
Use case
# List open PRs with a specific head branch$oldPRs=Get-GitHubPullRequest-Owner 'PSModule'-Repository 'GoogleFonts'-State 'Open'-Head 'auto-update'# Comment on each superseded PR and close itforeach ($prin$oldPRs) {
$pr|Add-GitHubPullRequestComment-Body 'Superseded by a newer Auto-Update PR.'$pr|Update-GitHubPullRequest-State 'Closed'
}
Technical decisions
Function grouping: Pull request functions go under src/functions/public/Pull-Requests/ (public) and src/functions/private/Pull-Requests/ (private), following the convention of grouping by object type. Comment functions go under src/functions/private/Issues/ since the API endpoint is the issues comments endpoint.
API approach: Use REST API (not GraphQL) for all pull request endpoints. The Pulls REST API provides straightforward endpoints and the Pull Request response object has many fields that don't map easily to a single GraphQL query. This matches the pattern used by Get-GitHubBranchList and Remove-GitHubRepository.
Public function names and their parameter sets:
Public function
Parameter sets
Maps to
Get-GitHubPullRequest
'List pull requests' (default), 'Get a pull request'
Comment function placement: The private function New-GitHubIssueComment lives under src/functions/private/Issues/ because it calls the issues API endpoint. The public function Add-GitHubPullRequestComment lives under src/functions/public/Pull-Requests/ because the user-facing context is pull requests. This private function can later be reused by a hypothetical Add-GitHubIssueComment public function.
Endpoints intentionally not covered in this issue:
POST /repos/{owner}/{repo}/pulls — Create a pull request (New-GitHubPullRequest) — separate issue
GET /repos/{owner}/{repo}/pulls/{pull_number}/commits — List PR commits — separate issue
GET /repos/{owner}/{repo}/pulls/{pull_number}/files — List PR files — separate issue
GET /repos/{owner}/{repo}/pulls/{pull_number}/merge — Check if merged — separate issue
PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge — Merge a PR (Merge-GitHubPullRequest) — separate issue
PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch — Update PR branch — separate issue
Test approach: Unit tests with mocked API responses using Pester. One test per parameter set per function, plus edge cases (empty list, not found, etc.).
Implementation plan
Classes
Add GitHubPullRequest class in src/classes/public/PullRequests/GitHubPullRequest.ps1 extending GitHubNode, with constructor mapping from REST API response fields to PascalCase properties
Add GitHubIssueComment class in src/classes/public/Issues/GitHubIssueComment.ps1 extending GitHubNode, with constructor mapping from REST API response fields
Add src/types/GitHubPullRequest.Types.ps1xml with alias property PullRequest → Number
Add src/types/GitHubIssueComment.Types.ps1xml with alias property IssueComment → ID
Private functions
Add Get-GitHubPullRequestList in src/functions/private/Pull-Requests/Get-GitHubPullRequestList.ps1 — calls GET /repos/{owner}/{repo}/pulls with optional State, Head, Base, Sort, Direction query parameters
Add Get-GitHubPullRequestByNumber in src/functions/private/Pull-Requests/Get-GitHubPullRequestByNumber.ps1 — calls GET /repos/{owner}/{repo}/pulls/{pull_number}
Add Update-GitHubPullRequestByNumber in src/functions/private/Pull-Requests/Update-GitHubPullRequestByNumber.ps1 — calls PATCH /repos/{owner}/{repo}/pulls/{pull_number} with body containing optional title, body, state, base, maintainer_can_modify
Add New-GitHubIssueComment in src/functions/private/Issues/New-GitHubIssueComment.ps1 — calls POST /repos/{owner}/{repo}/issues/{issue_number}/comments with body containing body
Public functions
Add Get-GitHubPullRequest in src/functions/public/Pull-Requests/Get-GitHubPullRequest.ps1 — with parameter sets 'List pull requests' (default) and 'Get a pull request', pipeline support via ValueFromPipelineByPropertyName, context resolution, and switch routing to private functions
Add Update-GitHubPullRequest in src/functions/public/Pull-Requests/Update-GitHubPullRequest.ps1 — with SupportsShouldProcess, pipeline support, parameters for Title, Body, State, Base, MaintainerCanModify
Add Add-GitHubPullRequestComment in src/functions/public/Pull-Requests/Add-GitHubPullRequestComment.ps1 — with SupportsShouldProcess, pipeline support, calls private New-GitHubIssueComment
Tests
Add tests for Get-GitHubPullRequest — list (with filters), get by number, empty results
Context
The GitHub PowerShell module is used to automate repository management tasks, including workflows that create and manage pull requests. For example, in PSModule/GoogleFonts, an automated workflow updates font data and opens a PR. When a new Auto-Update PR is created, older Auto-Update PRs should be commented on (explaining they are superseded) and then closed.
Currently, no commands exist in the module for interacting with pull requests. The only workaround is shelling out to the
ghCLI, which breaks consistency with the rest of the module and loses the typed object pipeline experience.Request
The module needs commands to list, retrieve, update, and comment on pull requests. Specifically, the following capabilities are missing:
What is expected
Get-GitHubPullRequestreturns pull request objects with typed properties (state, head/base branch, author, labels, draft status, merge state, etc.)Update-GitHubPullRequestallows changing state toclosed(or reopening), updating title/body/base, withSupportsShouldProcessAdd-GitHubPullRequestCommentposts a comment to a pull request and returns the comment objectAcceptance criteria
GitHubPullRequestclass (andGitHubIssueCommentclass for comments)Contextresolution patternUse case
Technical decisions
Function grouping: Pull request functions go under
src/functions/public/Pull-Requests/(public) andsrc/functions/private/Pull-Requests/(private), following the convention of grouping by object type. Comment functions go undersrc/functions/private/Issues/since the API endpoint is the issues comments endpoint.API approach: Use REST API (not GraphQL) for all pull request endpoints. The Pulls REST API provides straightforward endpoints and the Pull Request response object has many fields that don't map easily to a single GraphQL query. This matches the pattern used by
Get-GitHubBranchListandRemove-GitHubRepository.Public function names and their parameter sets:
Get-GitHubPullRequest'List pull requests'(default),'Get a pull request'Get-GitHubPullRequestList,Get-GitHubPullRequestByNumberUpdate-GitHubPullRequestUpdate-GitHubPullRequestByNumberAdd-GitHubPullRequestCommentNew-GitHubIssueCommentPrivate function names (one API call = one function):
Get-GitHubPullRequestListGET /repos/{owner}/{repo}/pullsGet-GitHubPullRequestByNumberGET /repos/{owner}/{repo}/pulls/{pull_number}Update-GitHubPullRequestByNumberPATCH /repos/{owner}/{repo}/pulls/{pull_number}New-GitHubIssueCommentPOST /repos/{owner}/{repo}/issues/{issue_number}/commentsClass design:
GitHubPullRequestextendsGitHubNode(providesIDandNodeID). Key properties:Number,State,Title,Body,Locked,ActiveLockReason,Draft,Head(branch ref info),Base(branch ref info),User(GitHubOwner),Labels,Milestone,Assignees,RequestedReviewers,RequestedTeams,CreatedAt,UpdatedAt,ClosedAt,MergedAt,MergeCommitSha,Merged,Mergeable,MergeableState,RebaseMergeable,MergedBy,Comments,ReviewComments,Commits,Additions,Deletions,ChangedFiles,MaintainerCanModify,AuthorAssociation,AutoMerge,Url,HtmlUrl,DiffUrlGitHubIssueCommentextendsGitHubNode. Key properties:Body,User(GitHubOwner),CreatedAt,UpdatedAt,AuthorAssociation,HtmlUrl,IssueUrlGitHubPullRequest.Types.ps1xml(aliasPullRequest→Number),GitHubIssueComment.Types.ps1xmlParameter naming:
Ownerwith aliasesOrganization,User(standard)Repository(notRepo, with[Alias('Repo')]if needed)Numberfor the pull request number (notID— sinceIDis the database ID per module conventions, and the PR number is not the database ID)Statewith[ValidateSet('Open', 'Closed', 'All')]for filteringHeadandBaseas[string]for branch filtering on listSortwith[ValidateSet('Created', 'Updated', 'Popularity', 'LongRunning')]Directionwith[ValidateSet('Asc', 'Desc')]ShouldProcess:
Get-GitHubPullRequest— noSupportsShouldProcess(read-only)Update-GitHubPullRequest—[CmdletBinding(SupportsShouldProcess)](modifies state)Add-GitHubPullRequestComment—[CmdletBinding(SupportsShouldProcess)](creates content)Comment function placement: The private function
New-GitHubIssueCommentlives undersrc/functions/private/Issues/because it calls the issues API endpoint. The public functionAdd-GitHubPullRequestCommentlives undersrc/functions/public/Pull-Requests/because the user-facing context is pull requests. This private function can later be reused by a hypotheticalAdd-GitHubIssueCommentpublic function.Endpoints intentionally not covered in this issue:
POST /repos/{owner}/{repo}/pulls— Create a pull request (New-GitHubPullRequest) — separate issueGET /repos/{owner}/{repo}/pulls/{pull_number}/commits— List PR commits — separate issueGET /repos/{owner}/{repo}/pulls/{pull_number}/files— List PR files — separate issueGET /repos/{owner}/{repo}/pulls/{pull_number}/merge— Check if merged — separate issuePUT /repos/{owner}/{repo}/pulls/{pull_number}/merge— Merge a PR (Merge-GitHubPullRequest) — separate issuePUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch— Update PR branch — separate issueTest approach: Unit tests with mocked API responses using Pester. One test per parameter set per function, plus edge cases (empty list, not found, etc.).
Implementation plan
Classes
GitHubPullRequestclass insrc/classes/public/PullRequests/GitHubPullRequest.ps1extendingGitHubNode, with constructor mapping from REST API response fields to PascalCase propertiesGitHubIssueCommentclass insrc/classes/public/Issues/GitHubIssueComment.ps1extendingGitHubNode, with constructor mapping from REST API response fieldssrc/types/GitHubPullRequest.Types.ps1xmlwith alias propertyPullRequest→Numbersrc/types/GitHubIssueComment.Types.ps1xmlwith alias propertyIssueComment→IDPrivate functions
Get-GitHubPullRequestListinsrc/functions/private/Pull-Requests/Get-GitHubPullRequestList.ps1— callsGET /repos/{owner}/{repo}/pullswith optionalState,Head,Base,Sort,Directionquery parametersGet-GitHubPullRequestByNumberinsrc/functions/private/Pull-Requests/Get-GitHubPullRequestByNumber.ps1— callsGET /repos/{owner}/{repo}/pulls/{pull_number}Update-GitHubPullRequestByNumberinsrc/functions/private/Pull-Requests/Update-GitHubPullRequestByNumber.ps1— callsPATCH /repos/{owner}/{repo}/pulls/{pull_number}with body containing optionaltitle,body,state,base,maintainer_can_modifyNew-GitHubIssueCommentinsrc/functions/private/Issues/New-GitHubIssueComment.ps1— callsPOST /repos/{owner}/{repo}/issues/{issue_number}/commentswith body containingbodyPublic functions
Get-GitHubPullRequestinsrc/functions/public/Pull-Requests/Get-GitHubPullRequest.ps1— with parameter sets'List pull requests'(default) and'Get a pull request', pipeline support viaValueFromPipelineByPropertyName, context resolution, and switch routing to private functionsUpdate-GitHubPullRequestinsrc/functions/public/Pull-Requests/Update-GitHubPullRequest.ps1— withSupportsShouldProcess, pipeline support, parameters forTitle,Body,State,Base,MaintainerCanModifyAdd-GitHubPullRequestCommentinsrc/functions/public/Pull-Requests/Add-GitHubPullRequestComment.ps1— withSupportsShouldProcess, pipeline support, calls privateNew-GitHubIssueCommentTests
Get-GitHubPullRequest— list (with filters), get by number, empty resultsUpdate-GitHubPullRequest— update state, update title/body, ShouldProcess behaviorAdd-GitHubPullRequestComment— add comment, ShouldProcess behaviorDocumentation