1
votes

According to the MS documentation, the 'refs' API for VSTS should allow you to create a new branch from a specific commit, but I can't seem to get it to work. Here's the POC code I have (in PowerShell):

$uri = 'https://{account}.visualstudio.com/{project}/_apis/git/repositories/{repository}/refs?api-version=1.0';

[array]$requestList = @();
$requestObj = New-Object -TypeName psobject;
$requestObj | Add-Member -MemberType NoteProperty -Name "name" -Value 'refs/heads/api-branch1';
$requestObj | Add-Member -MemberType NoteProperty -Name "oldObjectId" -Value "0000000000000000000000000000000000000000";
$requestObj | Add-Member -MemberType NoteProperty -Name "newObjectId" -Value "272c5f931889e5c6cc61a6fdb19ad00eeebf2d77";
$requestList += @($requestObj);

$header = Get-AuthHeader;
$body = ConvertTo-Json -InputObject @($requestList);
Write-Host $body;

$response = Invoke-RestMethod -Uri $uri -Headers $header -Method Post -Body $body -ContentType application/json;

Write-Host $response;

The request body is formatted correctly, as reported by the Write-Host statement, and I've verified that the newObjectId is the correct commit ID. However, when I run the script I get the following error:

Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Value cannot be null.\r\nParameter name: refUpdates","typeName":"System.ArgumentNullException, mscorlib, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089","typeKey":"ArgumentNullException","errorCode":0,"eventId":0}
At C:\Users\gappleton\Documents\VSTS\Scripts\Test-Methods.ps1:119 char:13
+ $response = Invoke-RestMethod -Uri $uri -Headers $header -Method Post ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Has anyone used this API to create a new ref (branch or tag) successfully, and if so, can you help me identify what I'm doing wrong? Below is a link to the MS documentation on the API, and thanks in advance for any help you can provide!

Git Refs : VSTS REST API Documentation

1

1 Answers

6
votes

Found it, and corrected it in my code example. Two things to consider to make this work. First, if you're using a PSObject and converting it to JSON, don't use the pipe "|" method of conversion as it will flatten arrays of 1 item to a non-array. If the request body does not contain a collection / array (square brackets), it will not be able to read the request.

$body = $requestList | ConvertTo-Json | Out-String; # Flattens one element array
$body = ConvertTo-Json -InputObject @($requestList); # Does not flatten

Second, when testing your code, make sure you pass the JSON converted string as opposed to the PSObject in the request body (that was a "DOH!" moment on my part). This example code actually works to create a new branch from a commit ID, once you replace the bracketed information in the uri accordingly:

$uri = 'https://{account}.visualstudio.com/{project}/_apis/git/repositories/{repository}/refs?api-version=1.0';

[array]$requestList = @();
$requestObj = New-Object -TypeName psobject;
$requestObj | Add-Member -MemberType NoteProperty -Name "name" -Value 'refs/heads/api-branch1';
$requestObj | Add-Member -MemberType NoteProperty -Name "oldObjectId" -Value "0000000000000000000000000000000000000000";
$requestObj | Add-Member -MemberType NoteProperty -Name "newObjectId" -Value "272c5f931889e5c6cc61a6fdb19ad00eeebf2d77";
$requestList += @($requestObj);

$header = Get-AuthHeader;
$body = ConvertTo-Json -InputObject @($requestList);
Write-Host $body;

$response = Invoke-RestMethod -Uri $uri -Headers $header -Method Post -Body $body -ContentType application/json;

Write-Host $response;