Skip to content

Instantly share code, notes, and snippets.

@flcdrg
Created June 22, 2018 06:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save flcdrg/8086adcea756e8616bb745a140a9bbda to your computer and use it in GitHub Desktop.
Save flcdrg/8086adcea756e8616bb745a140a9bbda to your computer and use it in GitHub Desktop.
Migrate Redmine issues to Visual Studio Team Services work items
param(
$user, # "VSTS username - doesn't need @domain suffix"
$token, # VSTS personal access token
$project, # the VSTS project to create items in
$vstsAccountName, # the bit before .visualstudio.com
$csvFile, # path to the .csv file
$redmineIssueUrl # URL to legacy redmine server. eg. https://redmine/issues
)
$ErrorActionPreference = "Stop"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}
# Get users (if you need to map between usernames)
# $result=Invoke-RestMethod -Method GET -Uri "https://$($vstsAccountName).vsaex.visualstudio.com/_apis/userentitlements?api-version=5.0-preview.1" -Headers $headers
#
# $userMap = @{
# }
#
# $result.value | ForEach-Object {
# $userMap.Add($_.user.displayName, $_.user.displayName)
# }
$priorityMap = @{
'High' = '1'
'Normal' = '2'
'Low' = '3'
}
$data = Import-Csv -Path $csvFile
foreach ($item in $data) {
switch ($item.Tracker) {
"Bug" {
$workItemType = "Bug"
$descriptionField = "Microsoft.VSTS.TCM.ReproSteps"
}
"Enhancement" {
$workItemType = "Product Backlog Item"
$descriptionField = "System.Description"
}
"Feature" {
$workItemType = "Product Backlog Item"
$descriptionField = "System.Description"
}
Default {
Write-Warning "Skipping $($item.Tracker)"
continue;
}
}
$bodyArray = @(
@{
op = "add"
path = "/fields/System.Title"
value = $item.Subject
}
@{
op = "add"
path = "/fields/$descriptionField"
value = $item.Description
}
@{
op = "add"
path = "/fields/Microsoft.VSTS.Common.Priority"
value = $priorityMap[$item.Priority]
}
@{
op = "add"
path = "/relations/-"
value = @{
rel = "Hyperlink"
url = "$($redmineIssueUrl)/$($item.ID)"
attributes = @{
comment = "Link to original ticket"
}
}
}
)
if ($item.Assignee -ne "") {
$bodyArray += @{
op = "add"
path = "/fields/System.AssignedTo"
value = $item.Assignee
}
}
$body = $bodyArray | ConvertTo-Json -Depth 3
$result=Invoke-RestMethod -Method PATCH -Uri "https://$($vstsAccountName).visualstudio.com/$($project)/_apis/wit/workitems/`$$($workItemType)?api-version=5.0-preview.3" -Headers $headers -ContentType "application/json-patch+json" -Body $body
Write-Host "Created item $($result.id) from legacy ticket $($item.ID)"
}
@wpoely86
Copy link

I've made a more extended version to migrate issue from redmine: https://github.com/wpoely86/redmine-azure-devops-migrate

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