Public/New-PSUADOPullRequest.ps1
function New-PSUADOPullRequest { <# .SYNOPSIS Creates a pull request in Azure DevOps using REST API. .DESCRIPTION This function submits a pull request (PR) from a specified source branch to a target branch in a given Azure DevOps repository. It authenticates using a Personal Access Token (PAT) and allows you to provide custom title and description content. You can specify the repository either by Repository ID or Repository Name. .PARAMETER Organization The Azure DevOps organization name (optional). Defaults to the ORGANIZATION environment variable. .PARAMETER Project The Azure DevOps project name. .PARAMETER RepoId The repository GUID in which to create the pull request. .PARAMETER Repository The repository name in which to create the pull request (optional). .PARAMETER SourceBranch The full name of the source branch (e.g., 'refs/heads/feature-branch') (optional). Defaults to current git branch. .PARAMETER TargetBranch The full name of the target branch (e.g., 'refs/heads/main') (optional). Defaults to the default branch from git. .PARAMETER Title The title of the pull request. .PARAMETER Description The detailed description of the pull request. .PARAMETER PAT The Azure DevOps Personal Access Token (PAT) used for authentication (optional). Defaults to the PAT environment variable. .EXAMPLE New-PSUADOPullRequest -Organization "myOrganization" -Project "MyProject" -RepoId "12345678-1234-1234-1234-123456789012" ` -SourceBranch "refs/heads/feature-x" -TargetBranch "refs/heads/main" ` -Title "Feature X Implementation" -Description "This PR adds feature X." Creates a pull request using repository ID. .EXAMPLE New-PSUADOPullRequest -Project "MyProject" -Repository "MyRepo" ` -Title "Bug fix for login" -Description "Fixed authentication issue" Creates a pull request using repository name with default source/target branches. .EXAMPLE New-PSUADOPullRequest -Organization "myOrganization" -Project "MyProject" -Repository "MyRepo" ` -SourceBranch "refs/heads/feature-branch" -TargetBranch "refs/heads/develop" ` -Title "New Feature" -Description "Added new functionality" -PAT $env:AZDO_PAT Creates a pull request using repository name with specific branches and PAT. .OUTPUTS [PSCustomObject] .NOTES Author: Lakshmanachari Panuganti Date: 2025-07-30 Updated: 2025-08-14 - Added Repository parameter and parameter sets .LINK https://github.com/lakshmanachari-panuganti https://www.powershellgallery.com/packages/OMG.PSUtilities.AzureDevOps https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-requests/create #> [CmdletBinding(DefaultParameterSetName = 'ByRepoName')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSAvoidUsingWriteHost', '', Justification = 'This is intended for this function to display formatted output to the user on the console' )] param ( [Parameter()] [ValidateNotNullOrEmpty()] [string]$Organization = $env:ORGANIZATION, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Project, [Parameter(Mandatory, ParameterSetName = 'ByRepoId')] [ValidateNotNullOrEmpty()] [string]$RepoId, [Parameter(Mandatory, ParameterSetName = 'ByRepoName')] [ValidateNotNullOrEmpty()] [string]$Repository, [Parameter()] [ValidateScript({ if ($_ -match '^refs/heads/.+') { $true } else { throw "SourceBranch must be in the format 'refs/heads/branch-name'." } })] [string]$SourceBranch = $("refs/heads/$((git branch --show-current).Trim())"), [Parameter()] [ValidateScript({ if ($_ -match '^refs/heads/.+') { $true } else { throw "TargetBranch must be in the format 'refs/heads/branch-name'." } })] [string]$TargetBranch = $("refs/heads/$((git symbolic-ref refs/remotes/origin/HEAD | Split-Path -Leaf).Trim())"), [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Title, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Description, [Parameter()] [ValidateNotNullOrEmpty()] [string]$PAT = $env:PAT ) process { try { # Resolve repository ID if needed $repositoryIdentifier = $null if ($PSCmdlet.ParameterSetName -eq 'ByRepoId') { $repositoryIdentifier = $RepoId } else { $repos = Get-PSUADORepositories -Project $Project -Organization $Organization -PAT $PAT $matchedRepo = $repos | Where-Object { $_.Name -eq $Repository } if (-not $matchedRepo) { throw "Repository '$Repository' not found in project '$Project'." } $repositoryIdentifier = $matchedRepo.Id } # Compose authentication header $headers = Get-PSUAdoAuthHeader -PAT $PAT $body = @{ sourceRefName = $SourceBranch targetRefName = $TargetBranch title = $Title description = ($Description -join "`n") } | ConvertTo-Json -Depth 10 $escapedProject = [uri]::EscapeDataString($Project) $uri = "https://dev.azure.com/$Organization/$escapedProject/_apis/git/repositories/$repositoryIdentifier/pullrequests?api-version=7.0" Write-Verbose "Creating pull request in project: $Project" Write-Verbose "Repository: $repositoryIdentifier" Write-Verbose "Source branch: $SourceBranch" Write-Verbose "Target branch: $TargetBranch" Write-Verbose "API URI: $uri" $response = Invoke-RestMethod -Method Post -Uri $uri -Headers $headers -Body $body -ContentType "application/json" -ErrorAction Stop $WebUrl = "https://dev.azure.com/$Organization/$escapedProject/_git/$repositoryIdentifier/pullrequest/$($response.pullRequestId)" Write-Host "Pull Request created successfully. PR ID: $($response.pullRequestId)" -ForegroundColor Green Write-Host "PR URL: $WebUrl" -ForegroundColor Cyan [PSCustomObject]@{ Id = $response.pullRequestId Title = $response.title Description = $response.description Status = $response.status IsDraft = $response.isDraft SourceBranch = $response.sourceRefName TargetBranch = $response.targetRefName CreatedBy = $response.createdBy.displayName CreatorEmail = $response.createdBy.uniqueName CreationDate = $response.creationDate RepositoryId = $response.repository.id RepositoryName = $response.repository.name ProjectName = $response.repository.project.name WebUrl = $WebUrl ApiUrl = $response.url PSTypeName = 'PSU.ADO.PullRequest' } } catch { $PSCmdlet.ThrowTerminatingError($_) } } } |