MethodsAndPractices / vsteam

PowerShell module for accessing Azure DevOps Services and Azure DevOps Server (formerly VSTS or TFS)
https://methodsandpractices.github.io/vsteam-docs/
MIT License
445 stars 155 forks source link

Update-VSTeamPullRequest - Cannot set status to "completed" #378

Closed DanielSSilva closed 3 years ago

DanielSSilva commented 3 years ago

Steps to reproduce

Add-VSTeamPullRequest -RepositoryId $repoId -SourceRefName "refs/heads/testPR" -TargetRefName "refs/heads/main" -Title "Testing PR from VSTeam PowerShellModule" - Description "Some description"

$prId = Get-VSTeamPullRequest -RepositoryId $repoId | Select-Object -ExpandProperty PullRequestId

Update-VSTeamPullRequest -RepositoryId $repoId -PullRequestId $prId -Status "completed"

Expected behavior

PR is completed without error

Actual behavior

Invoke-RestMethod: C:\Users\DanielSilva\Documents\PowerShell\Modules\VSTeam\7.1.2\vsteam.functions.ps1:251
Line |
 251 |           $resp = Invoke-RestMethod @params
     |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
     | {"$id":"1","innerException":null,"message":"Invalid argument value.\r\nParameter name: You must
     | specify a valid LastMergeSourceCommit to perform this
     | operation.","typeName":"Microsoft.TeamFoundation.SourceControl.WebServer.InvalidArgumentValueException, Microsoft.TeamFoundation.SourceControl.WebServer","typeKey":"InvalidArgumentValueException","errorCode":0,"eventId":0}

Environment data

OS

Server

> Get-VSTeamAPIVersion
Name                           Value
----                           -----
VariableGroups                 5.1-preview.1
Tfvc                           5.1
Graph                          6.0-preview
Pipelines                      5.1-preview
Version                        VSTS
Build                          5.1
HierarchyQuery                 5.1-preview
Release                        5.1
DistributedTask                6.0-preview
Git                            5.1
Processes                      6.0-preview
MemberEntitlementManagement    6.0-preview
Policy                         5.1
ExtensionsManagement           6.0-preview
Packaging                      6.0-preview
Core                           5.1
ServiceEndpoints               5.0-preview
DistributedTaskReleased        5.1
TaskGroups                     6.0-preview
> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      7.1.0-preview.7
PSEdition                      Core
GitCommitId                    7.1.0-preview.7
OS                             Microsoft Windows 10.0.19042
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Note: I can abandon a PR, but I cannot mark it as "completed". I've tried to look for the "LastMergeSourceCommit " parameter on the source code, but can't find anything related to that that can be filled from my side

DanielSSilva commented 3 years ago

After a long time of debugging, I've found the issue and a solution. Update-VSTeamPullRequest performs a PATCH request, where only the property being changed is sent. This is true for most cases, but it seems that when the status is "completed", it's different. Making the request on the Azure DevOps website, and using the developer console, I've found that the "complete" is a PATCH request that sends the status (so far, so good) but also requires a "lastMergeSourceCommit" object

image

I was able to modify the vsteam.functions.ps1 to include this object.

####### current code ##########
 # if ($Status) { 
         #    $body = '{"status": "' + $Status + '"}'
         # }
####### my change #########
         if ($Status) {
            if($Status -eq "completed")
            {
               $lastMergeSourceCommit = Get-VSTeamPullRequest -RepositoryId $RepositoryId | Where-Object {$_.pullRequestId -eq $PullRequestId} | Select-Object -ExpandProperty lastMergeSourceCommit | ConvertTo-Json
               $body = '{"status": "' + $Status + '", "lastMergeSourceCommit": ' + $lastMergeSourceCommit + '}'
               $body
            }
            else{
               $body = '{"status": "' + $Status + '"}'
            }
         }

Essentially my workaround was to fetch the lastMergeSourceCommit from the PR that is being requested to change, convert it to json and append to the body.

Here's the execution result (I've printed the body for debugging)

image

And here's the "proof" on DevOps image

I would love to contribute to this and submit a PR. I will try to understand how can I do so, but any pointers are welcome :)