After some research and a few hours later of testing in Postman/VSTS - I was able to write a powershell script that sends a API request to VSTS and commits a file to a repository.
I referenced the Create a push documentation here. I needed to determine the correct values for the following properties of the JSON request:
- oldObjectId - Which is not quite documented anywhere. The value needed here can be returned by calling list refs API. I believe this is similar to
git show HEAD
- changeType
- contentType
Here is an example to retrieve the latest objectId to use as the oldObjectId value:
Invoke-RestMethod -Uri "https://{accountName}.visualstudio.com/DefaultCollection/{project}/_apis/git/repositories/{repositoryId}/refs?filter=heads%2Fmaster&api-version=4.1-preview" -Method Get -Headers $header
My next task was to prepare the newContent property. Since I was trying to upload an XML file, rawText
was out of the question because of all the special characters. The only other contentType allowed is base64Encoded
.
I had to use Powershell's Get-Content
cmdlet with the -Raw
switch enabled in order to successfully base64 encode the content. I learned that from another StackOverflow post I made earlier when I was having problems with the formatting of the XML.
$xmlData = Get-Content -Path $xmlFile -Raw
$xmlDataEncoded = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($xmlData))
Then, in order to determine if I was adding a new file or modifying an existing file, I needed to add logic to the script to check for the existence of a file and set changeType to add
or edit
. See below:
$xmlDataRepo = Invoke-RestMethod -Uri "{accountName}.visualstudio.com/DefaultCollection/{project/_apis/git/repositories/{project}/items/?recursionLevel=OneLevel&api-version=4.1-preview" -Method Get -Headers $header
ForEach-Object -InputObject $xmlDataRepo.value -Process {if ($_.path -eq $repoXmlFile) {$changeType = "edit"} else {$changeType = "add"}}
Finally, now that I have collected all of the information and encoded my XML content. I need to build the request body and call the API. Here is the body of the request:
$body = @"
{
"refUpdates": [
{
"name": "refs/heads/master",
"oldObjectId": "$objectId"
}
],
"commits": [
{
"comment": "Data backed up",
"changes": [
{
"changeType": "$changeType",
"item": {
"path": "$repoXmlFile"
},
"newContent": {
"content": "$xmlDataEncoded",
"contentType": "base64Encoded"
}
}
]
}
]
}
"@
And finally, the cherry on top:
Invoke-RestMethod -Uri "https://{accountName}.visualstudio.com/DefaultCollection/{project/_apis/git/repositories/{project}/pushes?api-version=4.1-preview" -Method Post -Headers $header -Body $body -ContentType application/json
Hope that helps