How to destroy a branch in TFVC using the REST API? - powershell

I am looking to delete and then destroy a branch in TFVC (in Azure Devops) using the REST API and Powershell, but after checking the documentation I have to ask: is this possible using the API?
Using the GET documentation as a guide I could take a guess at it and run something similar to the following:
DELETE https://dev.azure.com/{organization}/{project}/_apis/tfvc/branches?path={path}&api-version=6.0
but given the destructive nature of these calls I am reluctant to guess. And there is no obvious way to invoke the destroy functionality.
Alternatively, is there a way to trace the API call that must (probably?) be executed if I was to run the command line tf vc destroy "$/MyBranch/Path"? Or am I going to have to resort to using a Powershell snapin for this?

Why not use tf vc destroy from powershell? Most of TFVC is handled by the old SOAP API and doesn't have a REST equivalent. The investment in more REST APIs for TFVC is unlikely. You can invoke tf vc from powershell assuming you have Team Explorer installed on the machine.
Alternatively, you can load the Client Object Model into PowerShell directly and invoke the destroy calls from it. The call is pretty straightforward. That way the Client Object Model will do all the API wrestling. You can get the assemblies from NuGet without installing Team Explorer to a machine.
To get an instance of the VersionControlServer class you can look at my TFVC tasks. The code below is untested, but should get you really close:
[System.Reflection.Assembly]::LoadFrom("Newtonsoft.Json.dll")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.Client")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.Common")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.VersionControl.Client")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.WorkItemTracking.Client")
[System.Reflection.Assembly]::LoadFrom("Microsoft.TeamFoundation.Diff")
$OnNonFatalError = [Microsoft.TeamFoundation.VersionControl.Client.ExceptionEventHandler] {
param($sender, $e)
if ($e.Exception -ne $null -and $e.Exception.Message -ne $null)
{
Write-Message -Type Warning $e.Exception.Message
}
if ($e.Failure -ne $null -and $e.Failure.Message -ne $null)
{
Write-Message -Type Warning $e.Failure.Message
if ($e.Failure.Warnings -ne $null -and $e.Failure.Warnings.Length -gt 0)
{
foreach ($warning in $e.Failure.Warnings)
{
Write-Message -Type Warning $warning.ParentOrChildTask
}
}
}
}
function Get-TfsVersionControlServer()
{
[cmdletbinding()]
param(
[string] $ProjectCollectionUri
)
$collection = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection(
$ProjectCollectionUri)
$collection.EnsureAuthenticated()
$versionControlServer =
$provider.TfsTeamProjectCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$versionControlServer.add_NonFatalError($OnNonFatalError)
return $versionControlServer
}
Get-TfsVersionControlServer().Destroy(...)
Then call the destroy function from there.

I looked at the API documentation as well. In my experience, Azure keeps their API documents up to date pretty well. The absence of the DELETE operation in their documentation indicates that the DELETE operation is not yet supported. Even if it 'worked', I wouldn't use it until it was supported in their API - especially with something dealing with version control.

Related

Use PowerShell to destroy source code marked for deletion in TFS, is this possible?

Example
If you look at the picture, I have marked some sample files/source in VS2017 source Control Explorer as deleted, but TFS doesn't delete it automatically, you have to destroy it manually with the tf destroy command.
I wanted to make PowerShell use the TFS REST API to get source that has been marked for deletion, but looking through their API reference, I haven't found a way to do this, it doesn't seem like the API exposes that kind of information, but somehow Visual Studio 2017 is able to get it, so surely I should be able to?
I'm using TFS2017 Update 2, so this is api version 3.2.
Why I want to do this: We're running low on space and we have lots of team project collections with source marked for deletion. It would be very tedious to destroy everything manually.
If you have TFS Power Tools you can use this PowerShell script to destory all the deleted items (with tf and not with rest api, but it does the work, you don't need to do it manually):
$tfsServer = Get-TfsServer -name http://YOURTFSSERVER:PORT
$destroyList = get-tfschilditem -item $/Root/ -server $tfsServer -Deleted -recurse | Where {$_.DeletionId -ne 0}
foreach($item in $destroyList)
{
$itemPath = '"' + $item.ServerItem + ";X" + $item.DeletionId + '"'
tf destroy $itemPath /i /startcleanup
}
There are no REST APIs for this. You will have to use tf.exe.

Forcing a powershell script to the next line

I have a powershell script that at one point will call 2 other powershell scripts to run. It runs one script to completion, then the other, but this causes it to take longer. Can I force the script to execute the other scripts and continue cycling through? When I used to run these scripts manually I would have 20-30 sessions running and walk away while it worked. What I wrote took the monotony of clicking through them manually
Here's the parent script:
$List = Get-Content C:\archive\${env:id}.txt
$Batch = New-Object System.Collections.ArrayList
foreach ($Data in $List){
if ($Data -eq "" -or $data -eq $List[-1]){
$ProjectName = $Batch[0]
out-file C:\archive\"$ProjectName".txt
foreach($Data in $Batch -ne $Batch[0]){
Add-Content -Path C:\archive\"$ProjectName".txt -Exclude
$Batch[0] -Value $Data
}
--> C:\archive\GetPrograms.ps1 $ProjectName
--> C:\archive\GetNetwork.ps1 $ProjectName
$Batch = New-Object System.Collections.ArrayList
}
else{
[void]$Batch.Add($Data)
}
}
The parent script is not contingent on the data produced by the other 2 scripts. It simply executes them by passing in data
Honestly, based on your use case description, you really want to be looking at Parallel job/task/script processing.
Here is a post along the lines of what should satisfy your goals.
How do I run my PowerShell scripts in parallel without using Jobs?
Update - While this answer explains the process and mechanics of
PowerShell runspaces and how they can help you multi-thread
non-sequential workloads, fellow PowerShell aficionado Warren 'Cookie
Monster' F has gone the extra mile and incorporated these same
concepts into a single tool called Invoke-Parallel - it does what I
describe below, and he has since expanded it with optional switches
for logging and prepared session state including imported modules,
really cool stuff - I strongly recommend you check it out before
building you own shiny solution!
https://serverfault.com/questions/626711/how-do-i-run-my-powershell-scripts-in-parallel-without-using-jobs

TFS 2017 How to rollback a release

Has anyone has a robust way to rollback if a release fails? The methods mentioned in this article doesn't sound very practical: https://blogs.msdn.microsoft.com/devops/2016/03/28/implement-rollback-with-release-management-for-tfs-2015/
IBM UrbanCode Deploy can choose to redeploy the previous successful deployment w/o any user intervention: https://developer.ibm.com/urbancode/videos/rollback-scenarios-in-ibm-urbancode-deploy/
Can we have that in TFS?
Once you install the Release Management Utility Tasks extension in your account, you’ll see a task called “Rollback powershell” in the task catalog. For rollback, you just need to add this task to the release definition and mark it “always run”.
An example to access the task execution information is as follows.
try
{
$jsonobject = ConvertFrom-Json $env:Release_Tasks
}
catch
{
Write-Verbose -Verbose “Error parsing Release_Tasks environment variable”
Write-Verbose -Verbose $Error
}
foreach ($task in $jsonobject | Get-Member -MemberType NoteProperty)
{
$taskproperty = $jsonobject.$($task.Name) | ConvertFrom-Json
Write-Verbose -Verbose “Task $($taskproperty.Name) with rank $($task.Name) has status $($taskproperty.Status)”
// Perform rollback action required in case $task.Name has status failed
}
Please notice, you may need to update the api version. Check the case below:
https://social.msdn.microsoft.com/Forums/expression/en-US/aacab4c3-b25b-4348-90b1-4d5661d9d148/release-management-utility-tasks-rollback-task-is-not-working-in-tfs-2017-update-1?forum=tfsbuild

Is there a powershell replacement for Repadmin /syncall

Currently we are using the command repadmin /syncall /e [our dn] and repadmin /syncall /eP [our dn] to force replication betwen domain controllers. I am wanting to use powershell to sync the domain controllers but everything I see online indicates that I would have to simply call repadmin from within powershell, which to me seems hokey and like duct taping something instead of doing it right. Is there any PURE powershell equivelant of repadmin /syncall?
I wrote this pure powershell function/script back last year to do exactly this and it looks like maybe that's where the other posted PS snippet answer here came from (I'll take as compliment). The other post saying it is not possible is absolutely incorrect this ADSI call and my script does in fact force a full sync just like a Repadmin /syncall simply test it and you will see - I use it quite a bit. It also does debug output and proper error checking. Here's the link to the Pure Powershell script on the MSDN site:
http://bit.ly/SyncADDomain
and the github repo where I even have the pure powershell script packaged into a MSI installer for simple deployment as well:
https://github.com/CollinChaffin/SyncADDomain
If you find it helpful please mark as answer. Thanks!
AFIAK there's not a full replacement for repadmin. Sync-ADObject will let you replicate a single object, but won't let you do a full sync. Also, that cmdlet is Windows 8.1/Windows Server 2012 R2 only. I would expect more comprehensive AD replication support in Windows Server vNext.
Give this script a try:
[CmdletBinding()]
Param([switch]$AllPartitions)
$myDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain();
ForEach ($dc in $myDomain.DomainControllers) {
$dcName = $dc.Name;
$partitions = #();
if ($AllPartitions) {
$partitions += $dc.Partitions;
} else {
$partitions += ([ADSI]"").distinguishedName;
}
ForEach ($part in $partitions) {
Write-Host "$dcName - Syncing replicas from all servers for partition '$part'"
$dc.SyncReplicaFromAllServers($part, 'CrossSite')
}
}

How do I get a list of all tfs alert subscriptions via powershell (get .Net assembly via PowerShell?)

I'm trying to move my tools to powershell, can this be done in PowerShell? the bit I'm really interested in is:
IEventService es = tfs.GetService(typeof(IEventService)) as IEventService;
List<Subscription> ls = es.GetAllEventSubscriptions().ToList();
Edit: what I really want to do might be using a .NET assembly from powershell and this might then be a duplicate of Using .NET library from PowerShell
Here is a TFS API in PowerShell function that I found on a blog long ago that will get you started. I've posted it to a GitHub Gist. Basically you ensure you've loaded up the TFS assemblies into the AppDomain and then you can add any TFS Service Interfaces you want to the object and just operate on them just as you would in any c# application, etc.
https://gist.github.com/3288447
Once you have the TFS object returned from the method in the Gist above, you can operate on the loaded services like so:
#use work item service
$tfs = get-tfs $env:TFSSERVERURL -silent
$project = $tfs.wit.Projects | ?{ $_.Name -eq $projectName}
#todo - replace with text for query or file read -- this is deprecated
$query = $project.StoredQueries | ?{ $_.Name -eq 'Active Bugs' }
$queryText = $query.QueryText.Replace("#project","'$projectName'")
$results = $tfs.wit.Query($queryText)
#do something with the results...
In your request above you can just alter the get-tfs method to add your service interface to the set loaded and then operate on the .NET methods much like I do in the example above.