Skip to content

Instantly share code, notes, and snippets.

@sevaa
Last active March 27, 2019 17:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sevaa/37b1c90a982784e7171fbb71fb82f370 to your computer and use it in GitHub Desktop.
Save sevaa/37b1c90a982784e7171fbb71fb82f370 to your computer and use it in GitHub Desktop.
A Powershell script to upload a TFS extension to an on-prem TFS instance with NTLM auth
param
(
[string]$Server,
[string]$File
)
try
{
Add-Type -Assembly "System.IO.Compression.FileSystem"
Add-Type -Assembly "System.Xml"
Add-Type -Assembly "System.Web"
# Resolve the wildcard file name to a specific file
$Files = dir $File | Sort-Object LastWriteTime -Descending
if(-not $Files)
{
Write-Error "$File not found"
exit 1
}
$File = $Files[0].FullName
Write-Host "Uploading $File to $Server"
# Retrieve the publisher and the package name from the XML manifest in the archive
$Package = [System.IO.Compression.ZipFile]::OpenRead($File)
$Manifest = $Package.Entries | ?{$_.Name -eq "extension.vsixmanifest"}
$ManifestXML = New-Object System.Xml.XmlDocument
$ManifestData = $Manifest.Open()
$ManifestXML.Load($ManifestData)
$ManifestData.Close()
$Package.Dispose()
$nsm = New-Object System.Xml.XmlNamespaceManager -ArgumentList $ManifestXML.NameTable
$nsm.AddNamespace("m", "http://schemas.microsoft.com/developer/vsx-schema/2011")
$IdElement = $ManifestXML.SelectSingleNode("/m:PackageManifest/m:Metadata/m:Identity", $nsm)
$PackageID = $IdElement.GetAttribute("Id")
$Publisher = $IdElement.GetAttribute("Publisher")
# Prepare and send the TFS REST HTTP request
$Package = [System.IO.File]::ReadAllBytes($File)
$JSON = '{"extensionManifest":"' + [Convert]::ToBase64String($Package) + '"}'
$wc = New-Object System.Net.WebClient
$wc.UseDefaultCredentials = $TRUE
$wc.Headers["Content-Type"] = "application/json"
$wc.Headers["Accept"] = "application/json; api-version=3.0-preview.1"
$wc.UploadString($Server + "_apis/gallery/publishers/" + $Publisher.ToLower() + "/extensions/" + $PackageID, "PUT", $JSON) | Out-Null
}
catch
{
Write-Error $_
if($_.Exception -and $_.Exception.InnerException -and $_.Exception.InnerException -is "System.Net.WebException")
{
$Resp = $_.Exception.InnerException.Response.GetResponseStream()
$SR = New-Object System.IO.StreamReader -ArgumentList $Resp
$RespData = $SR.ReadToEnd()
$SR.Close()
Write-Error $RespData
}
exit 1
}
@sevaa
Copy link
Author

sevaa commented Mar 2, 2018

A companion gist for http://rathertech.blogspot.com/2018/02/uploading-extensions-to-tfs.html

EDIT: tested on TFS Azure DevOps 2019, works as ever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment