Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions examples/PullRequests/PullRequests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Pull Request Management Examples

# This file contains examples of how to use the Pull Request management commands.

# Prerequisites: Connect to GitHub
# Connect-GitHubAccount

# Example 1: List all open pull requests in a repository
Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub'

# Example 2: List all pull requests (open and closed)
Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -State 'all'

# Example 3: Get a specific pull request by number
Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -Number 123

# Example 4: Filter pull requests by head branch
Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -Head 'PSModule:feature-branch'

# Example 5: Filter pull requests by base branch
Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -Base 'main' -State 'open'

# Example 6: Sort pull requests by last update
Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -Sort 'updated' -Direction 'desc'

# Example 7: Update a pull request title and body
Update-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -Number 123 -Title 'New title' -Body 'Updated description'

# Example 8: Close a pull request
Update-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -Number 123 -State 'closed'

# Example 9: Add a comment to a pull request
New-GitHubPullRequestComment -Owner 'PSModule' -Repository 'GitHub' -Number 123 -Body 'Thanks for your contribution!'

# Example 10: Close superseded PRs with a comment (use case from the issue)
# List all open PRs with a specific head branch pattern
$oldPRs = Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GoogleFonts' -Head 'PSModule:auto-update-*' -State 'open'

# Filter to get only the older ones (assuming we want to keep the most recent)
$oldPRs | Sort-Object -Property UpdatedAt | Select-Object -First ($oldPRs.Count - 1) | ForEach-Object {
# Add a comment explaining the PR is superseded
New-GitHubPullRequestComment -Owner $_.Owner -Repository $_.Repository -Number $_.Number -Body "This PR has been superseded by a newer Auto-Update PR and will be closed."

# Close the PR
Update-GitHubPullRequest -Owner $_.Owner -Repository $_.Repository -Number $_.Number -State 'closed'
}

# Example 11: Using pipeline to process multiple PRs
Get-GitHubPullRequest -Owner 'PSModule' -Repository 'GitHub' -State 'open' |
Where-Object { $_.Title -like '*WIP*' } |
New-GitHubPullRequestComment -Body 'Reminder: This PR is marked as Work In Progress'
147 changes: 147 additions & 0 deletions src/classes/public/PullRequests/GitHubPullRequest.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
class GitHubPullRequest : GitHubNode {
# The pull request number
[int] $Number

# The repository where the pull request is
[string] $Repository

# The owner of the repository
[string] $Owner

# The title of the pull request
[string] $Title

# The body/description of the pull request
[string] $Body

# The state of the pull request (open, closed)
[string] $State

# Whether the pull request is a draft
[bool] $IsDraft

# Whether the pull request is locked
[bool] $IsLocked

# Whether the pull request has been merged
[bool] $IsMerged

# The user who created the pull request
[GitHubUser] $Author

# The head branch (source branch)
[string] $HeadRef

# The head repository owner
[string] $HeadOwner

# The head repository name
[string] $HeadRepository

# The head SHA
[string] $HeadSHA

# The base branch (target branch)
[string] $BaseRef

# The base repository owner
[string] $BaseOwner

# The base repository name
[string] $BaseRepository

# The base SHA
[string] $BaseSHA

# Pull request URL
[string] $Url

# Timestamp when the pull request was created
[System.Nullable[datetime]] $CreatedAt

# Timestamp when the pull request was updated
[System.Nullable[datetime]] $UpdatedAt

# Timestamp when the pull request was closed
[System.Nullable[datetime]] $ClosedAt

# Timestamp when the pull request was merged
[System.Nullable[datetime]] $MergedAt

# User who merged the pull request
[GitHubUser] $MergedBy

# Number of commits in the pull request
[int] $Commits

# Number of additions in the pull request
[int] $Additions

# Number of deletions in the pull request
[int] $Deletions

# Number of changed files in the pull request
[int] $ChangedFiles

GitHubPullRequest() {}

GitHubPullRequest([PSCustomObject] $Object, [string] $Owner, [string] $Repository) {
if ($null -ne $Object.node_id) {
# REST API response mapping
$this.ID = $Object.id
$this.NodeID = $Object.node_id
$this.Number = $Object.number
$this.Title = $Object.title
$this.Body = $Object.body
$this.State = $Object.state
$this.IsDraft = $Object.draft
$this.IsLocked = $Object.locked
$this.IsMerged = $Object.merged
$this.Url = $Object.html_url
$this.Owner = $Owner
$this.Repository = $Repository
$this.Author = [GitHubUser]::new($Object.user)
$this.HeadRef = $Object.head.ref
$this.HeadOwner = if ($Object.head.repo) { $Object.head.repo.owner.login } else { $null }
$this.HeadRepository = if ($Object.head.repo) { $Object.head.repo.name } else { $null }
$this.HeadSHA = $Object.head.sha
$this.BaseRef = $Object.base.ref
$this.BaseOwner = if ($Object.base.repo) { $Object.base.repo.owner.login } else { $null }
$this.BaseRepository = if ($Object.base.repo) { $Object.base.repo.name } else { $null }
$this.BaseSHA = $Object.base.sha
$this.CreatedAt = $Object.created_at
$this.UpdatedAt = $Object.updated_at
$this.ClosedAt = $Object.closed_at
$this.MergedAt = $Object.merged_at
$this.MergedBy = if ($Object.merged_by) { [GitHubUser]::new($Object.merged_by) } else { $null }
$this.Commits = $Object.commits
$this.Additions = $Object.additions
$this.Deletions = $Object.deletions
$this.ChangedFiles = $Object.changed_files
} else {
# GraphQL response mapping
$this.ID = $Object.databaseId
$this.NodeID = $Object.id
$this.Number = $Object.number
$this.Title = $Object.title
$this.Body = $Object.body
$this.State = $Object.state
$this.IsDraft = $Object.isDraft
$this.IsLocked = $Object.locked
$this.IsMerged = $Object.merged
$this.Url = $Object.url
$this.Owner = $Owner
$this.Repository = $Repository
$this.Author = [GitHubUser]::new($Object.author)
$this.HeadRef = $Object.headRefName
$this.HeadSHA = $Object.headRefOid
$this.BaseRef = $Object.baseRefName
$this.BaseSHA = $Object.baseRefOid
$this.CreatedAt = $Object.createdAt
$this.UpdatedAt = $Object.updatedAt
$this.ClosedAt = $Object.closedAt
$this.MergedAt = $Object.mergedAt
$this.MergedBy = if ($Object.mergedBy) { [GitHubUser]::new($Object.mergedBy) } else { $null }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
filter Get-GitHubPullRequestByNumber {
<#
.SYNOPSIS
Get a pull request by number.

.DESCRIPTION
Gets a specific pull request in a repository by its pull request number.
Anyone with read access to the repository can use this endpoint.

.EXAMPLE
```powershell
Get-GitHubPullRequestByNumber -Owner 'octocat' -Repository 'Hello-World' -Number 1
```

Gets pull request #1 from the repository.

.OUTPUTS
GitHubPullRequest

.NOTES
[Get a pull request](https://docs.github.com/rest/pulls/pulls#get-a-pull-request)
#>
[OutputType([GitHubPullRequest])]
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')]
param(
# The account owner of the repository. The name is not case sensitive.
[Parameter(Mandatory)]
[string] $Owner,

# The name of the repository. The name is not case sensitive.
[Parameter(Mandatory)]
[string] $Repository,

# The number that identifies the pull request.
[Parameter(Mandatory)]
[int] $Number,

# The context to run the command in. Used to get the details for the API call.
[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/pulls/$Number"
Context = $Context
}

Invoke-GitHubAPI @apiParams | ForEach-Object {
[GitHubPullRequest]::new($_.Response, $Owner, $Repository)
}
}

end {
Write-Debug "[$stackPath] - End"
}
}
109 changes: 109 additions & 0 deletions src/functions/private/PullRequests/Get-GitHubPullRequestList.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
filter Get-GitHubPullRequestList {
<#
.SYNOPSIS
List pull requests in a repository.

.DESCRIPTION
Lists pull requests in a repository. You can use parameters to narrow the list of results.
Anyone with read access to the repository can use this endpoint.

.EXAMPLE
```powershell
Get-GitHubPullRequestList -Owner 'octocat' -Repository 'Hello-World'
```

Lists all pull requests in the repository.

.EXAMPLE
```powershell
Get-GitHubPullRequestList -Owner 'octocat' -Repository 'Hello-World' -State 'open' -Head 'octocat:new-feature'
```

Lists all open pull requests in the repository from the specified head branch.

.OUTPUTS
GitHubPullRequest

.NOTES
[List pull requests](https://docs.github.com/rest/pulls/pulls#list-pull-requests)
#>
[OutputType([GitHubPullRequest])]
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')]
param(
# The account owner of the repository. The name is not case sensitive.
[Parameter(Mandatory)]
[string] $Owner,

# The name of the repository. The name is not case sensitive.
[Parameter(Mandatory)]
[string] $Repository,

# Either 'open', 'closed', or 'all' to filter by state. Default: open
[Parameter()]
[ValidateSet('open', 'closed', 'all')]
[string] $State = 'open',

# Filter pulls by head user or head organization and branch name in the format of 'user:ref-name' or 'organization:ref-name'.
# For example: 'github:new-script-format' or 'octocat:test-branch'.
[Parameter()]
[string] $Head,

# Filter pulls by base branch name. Example: 'gh-pages'.
[Parameter()]
[string] $Base,

# What to sort results by. Can be either 'created', 'updated', 'popularity' (comment count) or 'long-running' (age, filtering by pulls updated in the last month). Default: created
[Parameter()]
[ValidateSet('created', 'updated', 'popularity', 'long-running')]
[string] $Sort = 'created',

# The direction of the sort. Can be either 'asc' or 'desc'. Default: desc when sort is 'created' or sort is not specified, otherwise asc.
[Parameter()]
[ValidateSet('asc', 'desc')]
[string] $Direction,

# 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.
[Parameter(Mandatory)]
[object] $Context
)

begin {
$stackPath = Get-PSCallStackPath
Write-Debug "[$stackPath] - Start"
Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT
}

process {
$body = @{
state = $State
head = $Head
base = $Base
sort = $Sort
direction = $Direction
}
$body | Remove-HashtableEntry -NullOrEmptyValues

$apiParams = @{
Method = 'GET'
APIEndpoint = "/repos/$Owner/$Repository/pulls"
Body = $body
PerPage = $PerPage
Context = $Context
}

Invoke-GitHubAPI @apiParams | ForEach-Object {
$_.Response | ForEach-Object {
[GitHubPullRequest]::new($_, $Owner, $Repository)
}
}
}

end {
Write-Debug "[$stackPath] - End"
}
}
Loading