When you have a TFS collection that has been running for a long time, as I do, you end with a lot of shelvesets.
The drawbacks of this is of course, (minor) storage, but it also affects upgrade time.
But instead of manually delete all the old obsoleted stuff manually, Powershell rescues us.
Note!! please be aware that removing shelvesets affects the revisions of your data. e.g. workitems might have links to shelvesets, so use it at your own risk.
First we need to extract all shelvesets from the collection. Unfortunately the API doesn’t allow to filter on dates, so we need to extract all, and then do the filtering clientside.
We get the shelvesets in batches of 1000
do { $result = (Invoke-RestMethod -Uri ($TFSServerURL + '/_apis/tfvc/shelvesets?$top=1000&$skip=' + $skip +'&api-version=1.0') -Method GET -UseDefaultCredentials).value | select name, createddate, @{N='Owner';E={$_.owner.uniquename}} $skip+=1000 } while ($result.count -eq 1000)
Then we can add a filter looking for shelvesets older than $RetentionTime days
$OldShelvesets += $result | where {[DateTime]$_.createddate -le [DateTime]::Now.AddDays(-$RetentionTime)}
When we have this, we can parse those values to the TF command, to actually remove them. (requires Visual Studio)
& $TFcmd vc shelve /collection:$TFSServerURL /delete "`"$($shelveset.name);$($ShelveSet.Owner)`""
The full script:
$TFSServerURL = "HTTP://[TFSCollectionURL]" $TFcmd = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\tf.exe" $LogFile = "d:\TFSShelveset.txt" $DeleteShelvesets = $True #Delete shelvesets or only generate log $RetentionTime = 720 #Remove shelveset older than x days #Remove Logfile if (Test-Path $LogFile) { Remove-Item $LogFile } #Get all shelvesets $skip=0 [System.Object[]] $OldShelvesets= $null do { write-host "Getting shelveset starting at" $skip $result = (Invoke-RestMethod -Uri ($TFSServerURL + '/_apis/tfvc/shelvesets?$top=1000&$skip=' + $skip +'&api-version=1.0') -Method GET -UseDefaultCredentials).value | select name, createddate, @{N='Owner';E={$_.owner.uniquename}} $skip+=1000 #Filter Shelvesets $OldShelvesets += $result | where {[DateTime]$_.createddate -le [DateTime]::Now.AddDays(-$RetentionTime)} } while ($result.count -eq 1000) #Cleanup foreach ($ShelveSet in $OldShelvesets) { "Removing shelveset $($ShelveSet.Owner) `t $($ShelveSet.Name)"| Out-File $LogFile -Append if ($DeleteShelvesets) { Write-Host "Removing Shelveset $($shelveset.name) owned by $($ShelveSet.Owner)" & $TFcmd vc shelve /collection:$TFSServerURL /delete "`"$($shelveset.name);$($ShelveSet.Owner)`"" } }
How to create a new TFS query using powershell
LikeLike