func_MergeRequests.ps1
# --------------------------------------------------------------------- # Group merge requests API # https://docs.gitlab.com/ee/api/merge_requests.html#list-group-merge-requests # get a list of group merge requests # (requires version 14.8) function Get-GitlabGroupMergeRequests( [Parameter(Mandatory=$true)] [string] $group , [Parameter(Mandatory=$false)][switch] $closed , [Parameter(Mandatory=$false)][switch] $merged , [Parameter(Mandatory=$false)][switch] $opened , [Parameter(Mandatory=$false)][switch] $simple , [Parameter(Mandatory=$false)][string] $labels , [Parameter(Mandatory=$false)][string] $milestone , [Parameter(Mandatory=$false)][string] $search , [Parameter(Mandatory=$false)][string] $source_branch , [Parameter(Mandatory=$false)][string] $target_branch ) { [string] $GAPI_MERGE = "$CI_API_V4_URL/groups/$group/merge_requests?scope=all&per_page=100&order_by=updated_at&sort=asc" if ($closed) { $GAPI_MERGE += "&state=closed" } elseif ($merged) { $GAPI_MERGE += "&state=merged" } elseif ($opened) { $GAPI_MERGE += "&state=opened" } if ($simple) { $GAPI_MERGE += "&view=simple" } if ($PSBoundParameters.ContainsKey('labels')) { $labels = [uri]::EscapeDataString($labels) $GAPI_MERGE += "&labels=$labels" } if ($PSBoundParameters.ContainsKey('milestone')) { $milestone = [uri]::EscapeDataString($milestone) $GAPI_MERGE += "&milestone=$milestone" } if (![string]::IsNullOrWhiteSpace($search)) { $search = [uri]::EscapeDataString($search) $GAPI_MERGE += "&search=$search" } if ($PSBoundParameters.ContainsKey('source_branch')) { $source_branch = [uri]::EscapeDataString($source_branch) $GAPI_MERGE += "&source_branch=$source_branch" } if ($PSBoundParameters.ContainsKey('target_branch')) { $target_branch = [uri]::EscapeDataString($target_branch) $GAPI_MERGE += "&target_branch=$target_branch" } return @(Invoke-WebRequestContentToJson -headers $GLPT -uri $GAPI_MERGE) } # --------------------------------------------------------------------- # Merge requests API # https://docs.gitlab.com/ee/api/merge_requests.html # get a list of merge requests from project # (requires version 14.8) function Get-GitlabMergeRequests( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$false)][switch] $closed , [Parameter(Mandatory=$false)][switch] $merged , [Parameter(Mandatory=$false)][switch] $opened , [Parameter(Mandatory=$false)][switch] $simple , [Parameter(Mandatory=$false)][string] $labels , [Parameter(Mandatory=$false)][string] $milestone , [Parameter(Mandatory=$false)][string] $search , [Parameter(Mandatory=$false)][string] $source_branch , [Parameter(Mandatory=$false)][string] $target_branch , [Parameter(Mandatory=$false)][string] $wip ) { [string] $GAPI_MERGE = "$CI_API_V4_URL/projects/$project/merge_requests?scope=all&per_page=100&order_by=updated_at&sort=asc" if ($closed) { $GAPI_MERGE += "&state=closed" } elseif ($merged) { $GAPI_MERGE += "&state=merged" } elseif ($opened) { $GAPI_MERGE += "&state=opened" } if ($simple) { $GAPI_MERGE += "&view=simple" } if ($PSBoundParameters.ContainsKey('labels')) { $labels = [uri]::EscapeDataString($labels) $GAPI_MERGE += "&labels=$labels" } if ($PSBoundParameters.ContainsKey('milestone')) { $milestone = [uri]::EscapeDataString($milestone) $GAPI_MERGE += "&milestone=$milestone" } if (![string]::IsNullOrWhiteSpace($search)) { $search = [uri]::EscapeDataString($search) $GAPI_MERGE += "&search=$search" } if ($PSBoundParameters.ContainsKey('source_branch')) { $source_branch = [uri]::EscapeDataString($source_branch) $GAPI_MERGE += "&source_branch=$source_branch" } if ($PSBoundParameters.ContainsKey('target_branch')) { $target_branch = [uri]::EscapeDataString($target_branch) $GAPI_MERGE += "&target_branch=$target_branch" } if ($PSBoundParameters.ContainsKey('wip')) { $GAPI_MERGE += "&wip=$wip" } return @(Invoke-WebRequestContentToJson -headers $GLPT -uri $GAPI_MERGE) } # get a single MR function Get-GitlabMergeRequest( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { [string] $GAPI_MERGE_IID = "$CI_API_V4_URL/projects/$project/merge_requests/$($iid)?include_diverged_commits_count=true&include_rebase_in_progress=true" return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID -method GET) } # modify an existing merge request # (requires version 13.8) function Set-GitlabMergeRequest( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid , [Parameter(Mandatory=$false)][string] $title , [Parameter(Mandatory=$false)][string] $description , [Parameter(Mandatory=$false)][string] $labels , [Parameter(Mandatory=$false)][string] $milestone , [Parameter(Mandatory=$false)][string] $squash , [Parameter(Mandatory=$false)][string] $assignee , [Parameter(Mandatory=$false)][string] $reviewer ) { [string] $GAPI_MERGE_IID = "$CI_API_V4_URL/projects/$project/merge_requests/$iid" $body_json = @{} if ($PSBoundParameters.ContainsKey('title')) { $body_json += @{ "title" = "$title" } } if ($PSBoundParameters.ContainsKey('description')) { [string] $desc_coded = $description -replace "\r\n", "`n" $body_json += @{ "description" = "$desc_coded" } } if ($PSBoundParameters.ContainsKey('labels')) { $body_json += @{ "labels" = "$labels" } } if ($PSBoundParameters.ContainsKey('milestone')) { [int] $milestone_id = Get-GitlabMilestoneID -project $project -title $milestone $body_json += @{ "milestone_id" = $milestone_id } } if ($PSBoundParameters.ContainsKey('squash')) { $body_json += @{ "squash" = "$squash" } } if ($PSBoundParameters.ContainsKey('assignee')) { [int] $assignee_id = Get-GitlabUserID $assignee $body_json += @{ "assignee_ids" = @( $assignee_id ) } } if ($PSBoundParameters.ContainsKey('reviewer')) { [int] $reviewer_id = Get-GitlabUserID $reviewer $body_json += @{ "reviewer_ids" = @( $reviewer_id ) } } if (!$body_json.Count) { return $null } [string] $body = $body_json | ConvertTo-Json -depth 10 return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID -method PUT -ContentType 'application/json' -body $body) } # create a new merge request # title and description can contain unescaped quotes " # description can be multiline, but markdown formatted function New-GitlabMergeRequest( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $title , [Parameter(Mandatory=$true)] [string] $source_branch , [Parameter(Mandatory=$false)][string] $target_branch = 'master' , [Parameter(Mandatory=$false)][string] $author , [Parameter(Mandatory=$false)][string] $assignee , [Parameter(Mandatory=$false)][string] $reviewer , [Parameter(Mandatory=$false)][string] $description , [Parameter(Mandatory=$false)][string] $labels , [Parameter(Mandatory=$false)][string] $milestone , [Parameter(Mandatory=$false)][string] $squash ) { [string] $title_coded = $title -replace '[\u201C\u201D\u201E\u201F]', '"' # “”„‟ $body_json = @{ "title" = "$title_coded"; "source_branch" = "$source_branch"; "target_branch" = "$target_branch"; "remove_source_branch" = "true"; } if (![string]::IsNullOrWhiteSpace($assignee)) { [int] $assignee_id = Get-GitlabUserID $assignee $body_json += @{ "assignee_ids" = @( $assignee_id ) } } if (![string]::IsNullOrWhiteSpace($reviewer)) { [int] $reviewer_id = Get-GitlabUserID $reviewer $body_json += @{ "reviewer_ids" = @( $reviewer_id ) } } if (![string]::IsNullOrWhiteSpace($description)) { [string] $desc_coded = $description -replace "\r\n", "`n" $desc_coded = $desc_coded -replace '[\u201C\u201D\u201E\u201F]', '"' # “”„‟ $body_json += @{ "description" = "$desc_coded" } } if (![string]::IsNullOrWhiteSpace($labels)) { $body_json += @{ "labels" = "$labels" } } if (![string]::IsNullOrWhiteSpace($milestone)) { [int] $milestone_id = Get-GitlabMilestoneID -project $project -title $milestone $body_json += @{ "milestone_id" = $milestone_id } } if ($PSBoundParameters.ContainsKey('squash')) { $body_json += @{ "squash" = "$squash" } } [string] $GAPI_MERGE = "$CI_API_V4_URL/projects/$project/merge_requests" if (![string]::IsNullOrWhiteSpace($author)) { $GAPI_MERGE += "?sudo=$author" } [string] $body = $body_json | ConvertTo-Json -depth 10 return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE -method POST -ContentType 'application/json' -body $body) } # delete a merge request function Remove-GitlabMergeRequest( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { [string] $GAPI_MERGE_IID = "$CI_API_V4_URL/projects/$project/merge_requests/$iid" return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID -method DELETE) } # accept a merge request after pipeline succeeds function Merge-GitlabMergeRequest( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid , [Parameter(Mandatory=$false)][string] $remove_source_branch = 'true' , [Parameter(Mandatory=$false)][string] $squash ) { [string] $GAPI_MERGE_IID = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/merge" $body_json = @{ "merge_when_pipeline_succeeds" = "true"; "should_remove_source_branch" = "$remove_source_branch"; } if ($PSBoundParameters.ContainsKey('squash')) { $body_json += @{ "squash" = "$squash" } } [string] $body = $body_json | ConvertTo-Json -depth 10 return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID -method PUT -ContentType 'application/json' -body $body) } # cancel a merge that is waiting for pipeline to succeed function Stop-GitlabMergeRequest( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { [string] $GAPI_MERGE_IID_CANCEL = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/cancel_merge_when_pipeline_succeeds" return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID_CANCEL -method PUT) } # rebase a merge request function Invoke-GitlabMergeRequestRebase( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { [string] $GAPI_MERGE_IID_REBASE = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/rebase" $webreq = Invoke-WebRequest -headers $GLPT -uri $GAPI_MERGE_IID_REBASE -method PUT return $webreq.StatusCode } # get approvals of a merge request function Get-GitlabMergeRequestApprovals( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { [string] $GAPI_MERGE_IID_APPROVALS = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/approvals" return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID_APPROVALS -method GET) } # get unique authors from all commits of a merge request function Get-GitlabMergeRequestAuthors( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { $commits = Get-GitlabMergeRequestCommits -project $project -iid $iid [string[]] $authors = @() foreach ($commit in $commits) { if ($authors -notcontains $commit.author_email) { $authors += $commit.author_email } } return $authors } # get commits of a merge request function Get-GitlabMergeRequestCommits( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { [string] $GAPI_MERGE_IID_COMMITS = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/commits" return @(Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID_COMMITS -method GET) } # get merge request with changes function Get-GitlabMergeRequestChanges( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid ) { [string] $GAPI_MERGE_IID_CHANGES = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/changes" return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID_CHANGES -method GET) } # get merge request changes for a specific path function Get-GitlabMergeRequestDiff( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid , [Parameter(Mandatory=$true)] [string] $path ) { $mr = Get-GitlabMergeRequestChanges -project $project -iid $iid foreach ($change in $mr.changes) { if ($change.new_path -eq $path) { return $change.diff } } return '' } # delete older merge request pipelines function Remove-GitlabMergeRequestPipelines( [Parameter(Mandatory=$true)] [string] $project , [Parameter(Mandatory=$true)] [string] $iid , [Parameter(Mandatory=$true)] [int] $keep ) { [string] $GAPI_MERGE_IID_PIPELINES = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/pipelines?per_page=100" $mrppl = @(Invoke-WebRequestContentToJson -headers $GLPT -uri $GAPI_MERGE_IID_PIPELINES) if (-not ($keep -lt $mrppl.Count)) { return } $mr = Get-GitlabMergeRequest -project $project -iid $iid foreach ($index in ($mrppl.Count-1)..$keep) { $pipeline = $mrppl[$index] if ($pipeline.id -ne $mr.head_pipeline.id) { Remove-GitlabPipeline -project $project -id $pipeline.id Write-Host -NoNewline '.' } } Write-Host ' ' } |