-
-
Save morcibacsi/5fff0698275eb64e8455ac121e0d8d12 to your computer and use it in GitHub Desktop.
Migrate Redmine issues to TFS (Azure DevOps) work items
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
$user, # "TFS username - doesn't need @domain suffix" | |
$token, # TFS personal access token | |
$fileToImport, # path to the .json file | |
$redmineIssueUrl # URL to legacy redmine server. eg. https://redmine/issues | |
) | |
# The following command gets the open issues through the Redmine API: | |
# For reference check: http://www.redmine.org/projects/redmine/wiki/Rest_Issues | |
# Sample call | |
# http://redmine/issues.json?offset=0&limit=100&sort=id | |
# Set these according to your instance: | |
$serverUrl = 'http://desktop-9a6epju' | |
$collectionName = 'DefaultCollection' | |
$projectName = 'MyProject' | |
$apiVersion = '4.1' #check: https://docs.microsoft.com/en-us/azure/devops/integrate/concepts/rest-api-versioning?view=azure-devops | |
$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' | |
} | |
$jsonText = Get-Content $fileToImport -Encoding UTF8 | Out-String | |
$json = $jsonText | ConvertFrom-Json | |
$issues = $json.issues | |
foreach ($item in $issues) { | |
switch ($item.tracker.name) { | |
"Bug" { | |
$workItemType = "Bug" | |
$descriptionField = "Microsoft.VSTS.TCM.ReproSteps" | |
} | |
"Enhancement" { | |
$workItemType = "Product Backlog Item" | |
$descriptionField = "System.Description" | |
} | |
"Feature" { | |
$workItemType = "Product Backlog Item" | |
$descriptionField = "System.Description" | |
} | |
"New request" { | |
$workItemType = "Product Backlog Item" | |
$descriptionField = "System.Description" | |
} | |
Default { | |
$workItemType = "Product Backlog Item" | |
$descriptionField = "System.Description" | |
#Write-Warning "Skipping $($item.Tracker)" | |
#continue; | |
} | |
} | |
$itemsubject = $item.subject | |
$subject = '{0} (#{1})' -f $itemSubject, $item.id | |
$description = '{0}' -f $item.description -replace '\r\n', '<br>' -replace "\t", " - " | |
$description = $description -replace '•', '' | |
$bodyArray = @( | |
@{ | |
op = "add" | |
path = "/fields/System.Title" | |
value = $subject | |
} | |
@{ | |
op = "add" | |
path = "/fields/$descriptionField" | |
value = $description | |
} | |
@{ | |
op = "add" | |
path = "/relations/-" | |
value = @{ | |
rel = "Hyperlink" | |
url = "$($redmineIssueUrl)/$($item.id)" | |
attributes = @{ | |
comment = "Link to original ticket" | |
} | |
} | |
} | |
@{ | |
op = "add" | |
path = "/fields/System.CreatedDate" | |
value = $item.created_on | |
} | |
#@{ | |
# op = "add" | |
# path = "/fields/System.State" | |
# value = $item.status.name | |
#} | |
) | |
if ($item.assigned_to.name -ne "") { | |
$name = '{0}' -f $item.assigned_to.name | |
$bodyArray += @{ | |
op = "add" | |
path = "/fields/System.AssignedTo" | |
value = $name | |
} | |
} | |
$body = $bodyArray | ConvertTo-Json -Depth 3 | |
$uri = "$serverUrl/$collectionName/$projectName/_apis/wit/workitems/`$$($workItemType)?api-version=$apiVersion&bypassRules=true" | |
$body = [System.Text.Encoding]::UTF8.GetBytes($body) | |
Write-Host $uri | |
#Write-Host $body | |
$result = Invoke-RestMethod -Method POST -Uri $uri -Headers $headers -ContentType "application/json-patch+json" -Body $body | |
Write-Host "Created item $($result.id) from legacy ticket $($item.ID)" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've mode a more extended version of this script (it also migrated attachments, parent-child relations, etc) at https://github.com/wpoely86/redmine-azure-devops-migrate