Public/DataImportTool/Remove-WitWorkItemLinkType.ps1
|
function Remove-WitWorkItemLinkType { <# .SYNOPSIS Deletes a custom work item link type from the collection, recording its links first. .DESCRIPTION Azure DevOps Services does not accept custom link types, so the Data Import Tool requires them to be removed from the source collection before import. witadmin deletelinktype deletes every link of that type along with the definition, and those relationships cannot be recovered - so this command exports an inventory of them first and refuses to delete if that export fails. Pass -NoExport to delete without a record. Idempotent: a link type that is already absent reports "no change" and skips both the export and the delete. .PARAMETER ReferenceName The link type reference name, without an end suffix - e.g. 'Custom.Affects', not 'Custom.Affects-Forward'. .PARAMETER ExportPath Destination .json file for the link inventory. Defaults to today's export snapshot for the collection (see Export-WorkItemLinkInventory). .PARAMETER NoExport Skip the inventory and delete the link type outright. The relationships are unrecoverable. .PARAMETER Pat Personal access token for the inventory's REST calls. Omit to use the current Windows identity, which is the normal case on-premises. .EXAMPLE Remove-WitWorkItemLinkType -Collection $collection -ReferenceName 'Custom.Affects' .EXAMPLE Remove-WitWorkItemLinkType -Collection $collection -ReferenceName 'Custom.Affects' -ExportPath "$snapshot\json\affects-links.json" #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Collection, [Parameter(Mandatory)] [string]$ReferenceName, [string]$ExportPath, [switch]$NoExport, [string]$Pat, [string]$ApiVersion = '5.0', [string]$WitAdminPath ) Write-FixStep "Deleting custom link type '$ReferenceName' from the collection" $executable = Resolve-WitAdminPath -WitAdminPath $WitAdminPath $linkTypes = & $executable listlinktypes "/collection:$Collection" if ($LASTEXITCODE -ne 0) { throw "witadmin listlinktypes failed with exit code $LASTEXITCODE. $(($linkTypes -join ' ').Trim())" } # Anchored on word boundaries: a substring match would treat 'Custom.Affects' # as present when only 'Custom.AffectsMore' exists, and go on to export and # delete a link type that is not there. $pattern = '(^|\s)' + [regex]::Escape($ReferenceName) + '(\s|$)' if (-not ($linkTypes | Where-Object { $_ -match $pattern })) { Write-FixStep " link type '$ReferenceName' not found - no change" return } if ($NoExport) { Write-Warning "Deleting link type '$ReferenceName' without an inventory (-NoExport). Its links will be unrecoverable." } else { try { $inventory = Export-WorkItemLinkInventory -Collection $Collection -ReferenceName $ReferenceName ` -Path $ExportPath -Pat $Pat -ApiVersion $ApiVersion } catch { throw "Refusing to delete link type '$ReferenceName': its links could not be recorded first. Fix the export, or pass -NoExport to accept losing them. $_" } Write-FixStep " $($inventory.LinkCount) link(s) recorded in $($inventory.JsonPath)" } Invoke-WitAdminFix -WitAdminPath $WitAdminPath -Arguments @('deletelinktype', "/collection:$Collection", "/n:$ReferenceName", '/noprompt') } |