Skip to content

Instantly share code, notes, and snippets.

@riezebosch
Last active August 30, 2021 12:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save riezebosch/075496a5619e9c08b7cdc727fde945df to your computer and use it in GitHub Desktop.
Save riezebosch/075496a5619e9c08b7cdc727fde945df to your computer and use it in GitHub Desktop.
robocopy "\\some\share\containing\backup" "C:\some\local\drive" database-backup*.sqb /Z /ETA /TEE /W:2 /xo
Param(
$collection
)
$tfsconfig = "$env:ProgramFiles\Microsoft Team Foundation Server 15.0\Tools\TFSConfig.exe"
& $tfsconfig collection /detach /collectionName:$collection /continue
# source: https://stackoverflow.com/a/43899733/129269
[Reflection.Assembly]::Load("Microsoft.TeamFoundation.Client, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
[Reflection.Assembly]::Load("Microsoft.TeamFoundation.Common, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$TFSConfigurationServer = New-Object Microsoft.TeamFoundation.Client.TfsConfigurationServer(New-Object System.Uri("http://localhost:8080/tfs"))
$TFSJobService = $TFSConfigurationServer.GetService([Microsoft.TeamFoundation.Framework.Client.ITeamFoundationJobService])
Write-Host "Waiting for TFS" -NoNewline
do {
try {
$TFSConfigurationServer.Connect([Microsoft.TeamFoundation.Framework.Common.ConnectOptions]::None)
$connect = $true
} catch {
Write-Host "." -NoNewLine
}
}
while (!($connect))
<#
Team Foundation Server Periodic Identity Synchronization
544dd581-f72a-45a9-8de0-8cd3a5f29dfe
#>
foreach($Job in $TFSJobService.QueryJobs())
{
if($Job.JobId -eq "544dd581-f72a-45a9-8de0-8cd3a5f29dfe") { break }
}
$CurrentJobState = $Job.EnabledState
$NewState = [Microsoft.TeamFoundation.Framework.Common.TeamFoundationJobEnabledState]::FullyDisabled
$Job.EnabledState = $NewState
$TFSJobService.UpdateJob($Job)
# export agent queues from TFS
Param(
[string]$pat = $env:pat,
$collection
)
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat"))
$projects = (Invoke-RestMethod `
-Uri "http://localhost:8080/tfs/$collection/_apis/projects?api-version=2" `
-Headers @{Authorization="Basic $auth"} `
-Method Get `
-ContentType "application/json").value.name
($projects | % {
Invoke-RestMethod `
-Uri "http://localhost:8080/tfs/Microsoft1/$_/_apis/distributedtask/queues?api-version=3.2-preview" `
-Headers @{Authorization="Basic $auth"} `
-Method Get `
-ContentType "application/json"
}).value | ConvertTo-Json | sc queues.json
#first export agent queues from TFS
Param(
[string]$pat = $env:pat,
$account
)
$agentpools = (gc ./queues.json | ConvertFrom-Json).pool.name | select -Unique
$auth = $pat | %{ [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$_")) }
$agentpools | % { Invoke-RestMethod `
-Uri "https://$account.visualstudio.com/_apis/distributedtask/pools?api-version=4.1-preview.1" `
-Headers @{Authorization="Basic $auth"} `
-Method POST `
-ContentType "application/json" `
-Body (@{ name=$_; poolType="automation" } | ConvertTo-Json)
}
Param(
$collection,
$user,
$password
)
& sqlcmd -S . -Q "USE [Tfs_$collection]
CREATE LOGIN $user WITH PASSWORD = '$password'
CREATE USER $user FOR LOGIN $user WITH DEFAULT_SCHEMA=[dbo]
EXEC sp_addrolemember @rolename='TFSEXECROLE', @membername='$user'"
$import = gc import.json | ConvertFrom-Json
$import.Source = @{ Properties = @{ ConnectionString = "Data Source=$ip;Initial Catalog=$collection;Integrated Security=False;User ID=$user;Password=$password;Encrypt=True;TrustServerCertificate=True" }}
$import.Target.AccountName = "xxx"
$import.Properties.ImportType = "DryRun"
$import | ConvertTo-Json | sc import.json
# fill in the blanks
& "$tfsmigrator\TfsMigrator.exe" prepare /collection:$collection /tenantDomainName:$name /accountRegion:$region
$logfolder = gci $tfsmigrator\Logs\$collection\* -Directory | select -Last 1
Copy-Item $logfolder\import.json .
Param(
[Parameter(Mandatory=$true)][string]$pat = $env:pat
)
$ErrorActionPreference = "Continue"
$account = "***"
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat"))
$testtaskversion = (Invoke-RestMethod `
-Uri "https://$account.visualstudio.com/_apis/distributedtask/tasks/d9a4ee62-4f10-4146-8e06-274bd42b7453" `
-Headers @{Authorization="Basic $auth" } `
-Method Get `
-ContentType "application/json").value.version.major | Sort-Object -Descending | Select-Object -First 1
$projects = (Invoke-RestMethod `
-Uri "https://$account.visualstudio.com/DefaultCollection/_apis/projects" `
-Headers @{Authorization="Basic $auth" } `
-Method Get `
-ContentType "application/json").value.name
$projects | % {
Write-Output "Project: $_"
$builds = (Invoke-RestMethod `
-Uri "https://$account.visualstudio.com/$_/_apis/build/definitions" `
-Headers @{Authorization="Basic $auth"; Accept = "application/json; api-version=4.1-preview.6" } `
-Method Get `
-ContentType "application/json").value
$builds | Where-Object { $_.type -ne "xaml" } | % {
$build = Invoke-RestMethod `
-Uri $_.url `
-Headers @{Authorization="Basic $auth"; Accept = "application/json; api-version=4.1-preview.6" } `
-Method Get `
-ContentType "application/json"
$npmtasks = $build.process.phases.steps | Where-Object { $_.task.id -eq 'fe47e961-9fa8-4106-8639-368c022d43ad' }
$npmtasks | % {
if ($_.inputs.arguments -eq '' -and $_.inputs.command -match '([^\s]+)\s*(.*)') {
$_.inputs.command = $Matches[1]
$_.inputs.arguments = $Matches[2]
}
}
$testtasks = $build.process.phases.steps.task | Where-Object { $_.id -eq 'd9a4ee62-4f10-4146-8e06-274bd42b7453' -and $_.versionSpec -ne "$testtaskversion.*" }
$testtasks | % { $_.versionSpec = "$testtaskversion.*" }
$nugettasks = $build.process.phases.steps | Where-Object { $_.task.id -eq '333b11bd-d341-40d9-afcf-b32d5ce6f25b' -and -not($_.inputs.continueOnEmptyNupkgMatch) }
$nugettasks | %{ $_.inputs | Add-Member -NotePropertyName 'continueOnEmptyNupkgMatch' -NotePropertyValue $true }
if ($npmtasks -or $testtasks -or $nugettasks) {
$build | Add-Member -NotePropertyName Comment -NotePropertyValue "Fix nuget publish task to continue if no package match" -Force
Write-Output " updating $($_.name)"
Invoke-RestMethod `
-Uri $_.url `
-Headers @{Authorization="Basic $auth"; Accept = "application/json; api-version=4.1-preview.6" } `
-Method Put `
-ContentType "application/json" `
-Body ($build | ConvertTo-Json -Depth 100) | Out-Null
}
}
$releases = (Invoke-RestMethod `
-Uri "https://$account.vsrm.visualstudio.com/$_/_apis/release/definitions" `
-Headers @{Authorization="Basic $auth"; Accept = "application/json; api-version=4.1-preview" } `
-Method Get `
-ContentType "application/json").value
$releases | % {
$update = $false
$comment = "Reset build artifact source alias to match build definition name"
$release = Invoke-RestMethod `
-Uri $_.url `
-Headers @{Authorization="Basic $auth"} `
-Method Get `
-ContentType "application/json"
$release.artifacts | where { $_.type -eq "Build" } | %{
Try {
$build = Invoke-RestMethod `
-Uri "https://$account.visualstudio.com/$($release.artifacts.definitionReference.project.name)/_apis/build/definitions/$($release.artifacts.definitionReference.definition.id)" `
-Headers @{Authorization="Basic $auth"; Accept = "application/json; api-version=4.1-preview.6" } `
-Method Get `
-ContentType "application/json"
if ($build.name -ne $_.alias) {
Write-Host " $($release.name):"
Write-Host " source alias $($release.artifacts.alias)"
Write-Host " build definition $($build.name)"
$_.alias = $build.name
$update = $true
}
} Catch {
Write-Host " $($release.name):"
Write-Host " exception resolving build definition"
}
}
$mailtask = $release.environments.deployPhases.workflowTasks | Where-Object { $_.taskId -eq 'a41d805b-80c4-4b20-924d-b8d1cca9a43f' -and $_.enabled -eq $true }
$mailtask | % { $_.enabled = $false }
if ($update)
{
$release | Add-Member -NotePropertyName Comment -NotePropertyValue $comment
$body = [Text.Encoding]::UTF8.GetBytes($($release | ConvertTo-Json -Depth 100 -Compress))
# Special thanks to: https://blogs.msdn.microsoft.com/aseemb/2017/04/06/vs402903-the-specified-value-is-not-convertible-to-type-releasedefinition-make-sure-it-is-convertible-to-type-releasedefinition-and-try-again/
Invoke-RestMethod `
-Uri $_.url `
-Headers @{Authorization="Basic $auth"; Accept = "application/json; api-version=4.1-preview" } `
-Method Put `
-ContentType "application/json" `
-Body $body | Out-Null
}
}
}
Param(
$tfs
)
# snippet for starting witadmin with 8 concurrent jobs
$witadmin = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\TeamExplorer\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer'
$tpc = [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($tfs_url)
$css = $tpc.GetService("Microsoft.TeamFoundation.Server.ICommonStructureService3")
$projects = $css.ListProjects() | sort -Property Name
$types = (gci -Path "$localfolder\TypeDefinitions" -Filter "*.xml").FullName
foreach ($project in $projects.Name)
{
$running = Get-Job -State Running
if ($running.Count -ge 8)
{
$running | Wait-Job -Any
}
Write-Host "Start job for $project"
Start-Job -ScriptBlock {
$project = $args[0]
Write-Host "== Team Project: $name =="
foreach ($type in $types)
{
Write-Host "Import: $WITFilename"
&"$witadminpath\witadmin.exe" importwitd /collection:$tfs /f:$type /p:$name
}
} -ArgumentList ($project) -Name $project
}
Get-Job | Wait-Job | Receive-job -AutoRemoveJob -Wait
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment