0

The article Install Extension By Name describe how to install a extension from the marketplace by its name.

Is it also possible to install a extension locally to a Azure DevOps Server?

  1. Step: server_ip/_gallery/manage

  2. Step: Upload

enter image description here

  1. Step: Install

enter image description here

It would be great to make these steps programmatically.

Shayki Abramczyk
  • 36,824
  • 16
  • 89
  • 114
Mar Tin
  • 2,132
  • 1
  • 26
  • 46

2 Answers2

2

PowerShell Script for add or delete a Extension based on a .vsix file to a Azure DevOps Server extension gallery:

$PAT = "PersonalAccessToken"
$Uri = "http://ip:port"
$timeout = 30

#AUTHORIZATION HEADERS
$headers = @{
    "Authorization" = ('Basic {0}' -f [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)")))
    "If-Match"      = ""
}

#VARIABLE
$publisher = "YourPublisherName"
$extension = "YourExtensionName"
$vsix = "YourVsixPath.vsix"

#DELETE EXTENSION
$api = "api-version=5.0-preview.2"
$url = "$Uri/_apis/gallery/publishers/$publisher/extensions/$($extension)?$api"
$result = Invoke-RestMethod -Uri $url -Method DELETE -ContentType "application/json" -Headers $headers -TimeoutSec $timeout -Verbose
Write-Host $result

#ADD EXTENSION
$api = "api-version=3.0-preview.1"
$body = '{{"extensionManifest": "{0}"}}' -f ([Convert]::ToBase64String([IO.File]::ReadAllBytes($vsix)))
$url = "$Uri/_apis/gallery/extensions?$api"
$result = Invoke-RestMethod -Uri $url -Method POST -ContentType "application/json" -Headers $headers -Body $body -TimeoutSec $timeout -Verbose
Write-Host $result
Mar Tin
  • 2,132
  • 1
  • 26
  • 46
1

According to the docs this Rest API supported also in Azure DevOps Server 2019 (and even in TFS 2018):

https://{instance}/{collection}/_apis/extensionmanagement/installedextensionsbyname/{publisherName}/{extensionName}/{version}?api-version=5.0-preview.1
Shayki Abramczyk
  • 36,824
  • 16
  • 89
  • 114
  • 1
    but what can I do when my source (`visx`) is local and not a part of the marketplace? – Mar Tin Aug 13 '19 at 10:31
  • @MarTin My mistake, I didn't understand the question properly :( – Shayki Abramczyk Aug 13 '19 at 13:17
  • then I think it was my fault. I develop very small and custom extensions for a Azure DevOps Server. These extensions are private and can't be uploaded to the marketplace. So I have to install from local to the DevOps Server. The steps to achieve this, I describe in my question. My thoughts about [Install Extension By Name](https://learn.microsoft.com/en-us/rest/api/azure/devops/extensionmanagement/installed%20extensions/install%20extension%20by%20name?view=azure-devops-server-rest-5.0) was that is works only for extensions in the marketplace or was I am wrong? – Mar Tin Aug 14 '19 at 04:22
  • do you maybe know where a extension get sored on Azure DevOps Server? One approach could be to copy the content of a `visx` to that path and add all relevant entries to the sql database. – Mar Tin Aug 14 '19 at 10:30
  • 1
    @MarTin Check this: https://developercommunity.visualstudio.com/content/problem/610229/need-help-to-upload-local-vsix-extension-in-tfs-de.html – Shayki Abramczyk Aug 15 '19 at 10:03
  • thanks for that hint! I could reproduce the example. My last issue is - how could I create the `body = {"extensionManifest": "UEsDBAoAAAAIAAFSD0829+0AqgAAAJABAAAVAAA...` manually by my self? (this body is generated by the upload process, read out from browser console) – Mar Tin Aug 15 '19 at 11:21
  • @MarTin I don't know :/ if you edit the `.vsix` to `.zip` you can open it, inside there is a manifest file, but i don't know how to make it json body – Shayki Abramczyk Aug 15 '19 at 11:59
  • I found out, it is: `$body = '{{"extensionManifest": "{0}"}}' -f ([Convert]::ToBase64String([IO.File]::ReadAllBytes($visx)))`. Thanks for your help. – Mar Tin Aug 15 '19 at 12:06