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
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] $milestone
                                     )
{
  [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('milestone')) {
    $GAPI_MERGE += "&milestone=$milestone"
  }

  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
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] $milestone
                                , [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('milestone')) {
    $GAPI_MERGE += "&milestone=$milestone"
  }

  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
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] $assignee
                               , [Parameter(Mandatory=$false)][string] $reviewer
                               )
{
  $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('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

  [string] $GAPI_MERGE_IID = "$CI_API_V4_URL/projects/$project/merge_requests/$($iid)"
  return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE_IID -method PUT -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
                                  )
{
  [string] $GAPI_MERGE = "$CI_API_V4_URL/projects/$project/merge_requests/$iid/merge?merge_when_pipeline_succeeds=true&should_remove_source_branch=true"
  return (Invoke-RestMethod -headers $GLPT -uri $GAPI_MERGE -method PUT)
}

# 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 Rebase-GitlabMergeRequest( [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)
}

# 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 ' '
}