Skip to content

Commit 788465f

Browse files
rjmholtHowardWolosky
authored andcommitted
Add New-GitHubPullRequest command (#111)
Adds a command for creating new pull requests. Resolves #30
1 parent 7ea773c commit 788465f

File tree

2 files changed

+227
-0
lines changed

2 files changed

+227
-0
lines changed

GitHubPullRequests.ps1

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,229 @@ function Get-GitHubPullRequest
163163

164164
return Invoke-GHRestMethodMultipleResult @params
165165
}
166+
167+
function New-GitHubPullRequest
168+
{
169+
<#
170+
.SYNOPSIS
171+
Create a new pull request in the specified repository.
172+
173+
.DESCRIPTION
174+
Opens a new pull request from the given branch into the given branch in the specified repository.
175+
176+
The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub
177+
178+
.PARAMETER OwnerName
179+
Owner of the repository.
180+
If not supplied here, the DefaultOwnerName configuration property value will be used.
181+
182+
.PARAMETER RepositoryName
183+
Name of the repository.
184+
If not supplied here, the DefaultRepositoryName configuration property value will be used.
185+
186+
.PARAMETER Uri
187+
Uri for the repository.
188+
The OwnerName and RepositoryName will be extracted from here instead of needing to provide
189+
them individually.
190+
191+
.PARAMETER Title
192+
The title of the pull request to be created.
193+
194+
.PARAMETER Body
195+
The text description of the pull request.
196+
197+
.PARAMETER Issue
198+
The GitHub issue number to open the pull request to address.
199+
200+
.PARAMETER Head
201+
The name of the head branch (the branch containing the changes to be merged).
202+
203+
May also include the name of the owner fork, in the form "${fork}:${branch}".
204+
205+
.PARAMETER Base
206+
The name of the target branch of the pull request
207+
(where the changes in the head will be merged to).
208+
209+
.PARAMETER HeadOwner
210+
The name of fork that the change is coming from.
211+
212+
Used as the prefix of $Head parameter in the form "${HeadOwner}:${Head}".
213+
214+
If unspecified, the unprefixed branch name is used,
215+
creating a pull request from the $OwnerName fork of the repository.
216+
217+
.PARAMETER MaintainerCanModify
218+
If set, allows repository maintainers to commit changes to the
219+
head branch of this pull request.
220+
221+
.PARAMETER Draft
222+
If set, opens the pull request as a draft.
223+
224+
.PARAMETER AccessToken
225+
If provided, this will be used as the AccessToken for authentication with the
226+
REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated.
227+
228+
.PARAMETER NoStatus
229+
If this switch is specified, long-running commands will run on the main thread
230+
with no commandline status update. When not specified, those commands run in
231+
the background, enabling the command prompt to provide status information.
232+
If not supplied here, the DefaultNoStatus configuration property value will be used.
233+
234+
.OUTPUTS
235+
[PSCustomObject] An object describing the created pull request.
236+
237+
.EXAMPLE
238+
$prParams = @{
239+
OwnerName = 'Microsoft'
240+
Repository = 'PowerShellForGitHub'
241+
Title = 'Add simple file to root'
242+
Head = 'octocat:simple-file'
243+
Base = 'master'
244+
Body = "Adds a simple text file to the repository root.`n`nThis is an automated PR!"
245+
MaintainerCanModify = $true
246+
}
247+
$pr = New-GitHubPullRequest @prParams
248+
249+
.EXAMPLE
250+
New-GitHubPullRequest -Uri 'https://github.com/PowerShell/PSScriptAnalyzer' -Title 'Add test' -Head simple-test -HeadOwner octocat -Base development -Draft -MaintainerCanModify
251+
252+
.EXAMPLE
253+
New-GitHubPullRequest -Uri 'https://github.com/PowerShell/PSScriptAnalyzer' -Issue 642 -Head simple-test -HeadOwner octocat -Base development -Draft
254+
#>
255+
256+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")]
257+
[CmdletBinding(SupportsShouldProcess, DefaultParameterSetName='Elements_Title')]
258+
param(
259+
[Parameter(ParameterSetName='Elements_Title')]
260+
[Parameter(ParameterSetName='Elements_Issue')]
261+
[string] $OwnerName,
262+
263+
[Parameter(ParameterSetName='Elements_Title')]
264+
[Parameter(ParameterSetName='Elements_Issue')]
265+
[string] $RepositoryName,
266+
267+
[Parameter(
268+
Mandatory,
269+
ParameterSetName='Uri_Title')]
270+
[Parameter(
271+
Mandatory,
272+
ParameterSetName='Uri_Issue')]
273+
[string] $Uri,
274+
275+
[Parameter(
276+
Mandatory,
277+
ParameterSetName='Elements_Title')]
278+
[Parameter(
279+
Mandatory,
280+
ParameterSetName='Uri_Title')]
281+
[ValidateNotNullOrEmpty()]
282+
[string] $Title,
283+
284+
[Parameter(ParameterSetName='Elements_Title')]
285+
[Parameter(ParameterSetName='Uri_Title')]
286+
[string] $Body,
287+
288+
[Parameter(
289+
Mandatory,
290+
ParameterSetName='Elements_Issue')]
291+
[Parameter(
292+
Mandatory,
293+
ParameterSetName='Uri_Issue')]
294+
[int] $Issue,
295+
296+
[Parameter(Mandatory)]
297+
[string] $Head,
298+
299+
[Parameter(Mandatory)]
300+
[string] $Base,
301+
302+
[string] $HeadOwner,
303+
304+
[switch] $MaintainerCanModify,
305+
306+
[switch] $Draft,
307+
308+
[string] $AccessToken,
309+
310+
[switch] $NoStatus
311+
)
312+
313+
Write-InvocationLog
314+
315+
if (-not [string]::IsNullOrWhiteSpace($HeadOwner))
316+
{
317+
if ($Head.Contains(':'))
318+
{
319+
$message = "`$Head ('$Head') was specified with an owner prefix, but `$HeadOwner ('$HeadOwner') was also specified." +
320+
" Either specify `$Head in '<owner>:<branch>' format, or set `$Head = '<branch>' and `$HeadOwner = '<owner>'."
321+
322+
Write-Log -Message $message -Level Error
323+
throw $message
324+
}
325+
326+
# $Head does not contain ':' - add the owner fork prefix
327+
$Head = "${HeadOwner}:${Head}"
328+
}
329+
330+
$elements = Resolve-RepositoryElements
331+
$OwnerName = $elements.ownerName
332+
$RepositoryName = $elements.repositoryName
333+
334+
$telemetryProperties = @{
335+
'OwnerName' = (Get-PiiSafeString -PlainText $OwnerName)
336+
'RepositoryName' = (Get-PiiSafeString -PlainText $RepositoryName)
337+
}
338+
339+
$uriFragment = "/repos/$OwnerName/$RepositoryName/pulls"
340+
341+
$postBody = @{
342+
'head' = $Head
343+
'base' = $Base
344+
}
345+
346+
if ($PSBoundParameters.ContainsKey('Title'))
347+
{
348+
$description = "Creating pull request $Title in $RepositoryName"
349+
$postBody['title'] = $Title
350+
351+
# Body may be whitespace, although this might not be useful
352+
if ($Body)
353+
{
354+
$postBody['body'] = $Body
355+
}
356+
}
357+
else
358+
{
359+
$description = "Creating pull request for issue $Issue in $RepositoryName"
360+
$postBody['issue'] = $Issue
361+
}
362+
363+
if ($MaintainerCanModify)
364+
{
365+
$postBody['maintainer_can_modify'] = $true
366+
}
367+
368+
if ($Draft)
369+
{
370+
$postBody['draft'] = $true
371+
$acceptHeader = 'application/vnd.github.shadow-cat-preview+json'
372+
}
373+
374+
$restParams = @{
375+
'UriFragment' = $uriFragment
376+
'Method' = 'Post'
377+
'Description' = $description
378+
'Body' = ConvertTo-Json -InputObject $postBody -Compress
379+
'AccessToken' = $AccessToken
380+
'TelemetryEventName' = $MyInvocation.MyCommand.Name
381+
'TelemetryProperties' = $telemetryProperties
382+
'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus)
383+
}
384+
385+
if ($acceptHeader)
386+
{
387+
$restParams['AcceptHeader'] = $acceptHeader
388+
}
389+
390+
return Invoke-GHRestMethod @restParams
391+
}

PowerShellForGitHub.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
'New-GitHubIssue',
9494
'New-GitHubLabel',
9595
'New-GitHubMilestone',
96+
'New-GitHubPullRequest',
9697
'New-GitHubRepository',
9798
'New-GitHubRepositoryFork',
9899
'Remove-GithubAssignee',

0 commit comments

Comments
 (0)