Skip to content

Commit 635e73d

Browse files
authored
Bug/epiclink not set #51 (#53)
Fixes issue where incorrect epic parent field mapping would cause the tool to err out.
1 parent 012352b commit 635e73d

File tree

11 files changed

+60
-54
lines changed

11 files changed

+60
-54
lines changed

docs/Samples/config-scrum.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"workspace": "C:\\Temp\\JiraExport\\",
66
"epic-link-field": "Epic Link",
77
"sprint-field": "Sprint",
8+
"download-options": 7,
89
"batch-size": 20,
910
"log-level": "Info",
1011
"attachment-folder": "Attachments",

docs/config.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ The migration configuration file is defined in a json file with the properties d
2424
|**epic-link-field**|False|string|Jira name of epic link field. Default = "Epic Link". **Note:** requires customization per account and sometimes project|
2525
|**sprint-field**|False|string|Jira name of sprint field. Default = "Sprint". **Note:** requires customization per account and sometimes project|
2626
|**batch-size**|False|integer|Number of items to retrieve with one call. Default = 20.|
27+
|**download-options**|False|integer|Type of related issues to migrate, see **Download options** below|
2728
|**log-level**|False|string|Debug, Info, Warning, Error or Critical. Default = "Debug".|
2829
|**attachment-folder**|True|string|Location to store attachments.|
2930
|**user-mapping-file**|False|string|Name of user mapping file. If no specific path is set the program expects it to be located in the "workspace" folder.|
@@ -35,6 +36,18 @@ The migration configuration file is defined in a json file with the properties d
3536
|**type-map**|True|json|List of the work item **types** you want to migrate from Jira to Azure DevOps/TFS.|
3637
|**field-map**|True|json|List of **fields** you want to migrate from a Jira item to a Azure DevOps/TFS work item.|
3738

39+
## Download options
40+
This option allows the tool to download related issues to cover cases where these are not included in the section query (like a parent issue).
41+
42+
Default value: 7 (=all)
43+
44+
|Option|Value|
45+
|---|---|
46+
|None|0|
47+
|IncludeParentEpics|1|
48+
|IncludeParents|2|
49+
|IncludeSubItems|4|
50+
3851
## Link properties
3952
Name-value pairs of work item link types to map in the migration.
4053

@@ -81,6 +94,7 @@ Name-value pairs of field values to map in the migration.
8194
"workspace": "C:\\Temp\\JiraExport\\",
8295
"epic-link-field": "Epic Link",
8396
"sprint-field": "Sprint",
97+
"download-options": 7,
8498
"batch-size": 20,
8599
"log-level": "Debug",
86100
"attachment-folder": "Attachments",

src/WorkItemMigrator/JiraExport/App.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
</assemblyBinding>
1717
</runtime>
1818
<appSettings>
19-
<add key="applicationInsightsKey" value="__APP_INSIGHTS_KEY__" />
19+
<add key="applicationInsightsKey" value="584b887e-5d80-41c3-8303-9f421d46c421" />
2020
</appSettings>
2121
</configuration>
Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
33
<TelemetryInitializers>
4-
<Add Type="Microsoft.ApplicationInsights.DependencyCollector.HttpDependenciesParsingTelemetryInitializer, Microsoft.AI.DependencyCollector"/>
54
</TelemetryInitializers>
65
<TelemetryModules>
7-
<Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector">
8-
<ExcludeComponentCorrelationHttpHeadersOnDomains>
9-
<!--
10-
Requests to the following hostnames will not be modified by adding correlation headers.
11-
Add entries here to exclude additional hostnames.
12-
NOTE: this configuration will be lost upon NuGet upgrade.
13-
-->
14-
<Add>core.windows.net</Add>
15-
<Add>core.chinacloudapi.cn</Add>
16-
<Add>core.cloudapi.de</Add>
17-
<Add>core.usgovcloudapi.net</Add>
18-
</ExcludeComponentCorrelationHttpHeadersOnDomains>
19-
<IncludeDiagnosticSourceActivities>
20-
<Add>Microsoft.Azure.EventHubs</Add>
21-
<Add>Microsoft.Azure.ServiceBus</Add>
22-
</IncludeDiagnosticSourceActivities>
23-
</Add>
246
</TelemetryModules>
257
<ApplicationIdProvider Type="Microsoft.ApplicationInsights.Extensibility.Implementation.ApplicationId.ApplicationInsightsApplicationIdProvider, Microsoft.ApplicationInsights"/>
268
</ApplicationInsights>

src/WorkItemMigrator/JiraExport/JiraCommandLine.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Newtonsoft.Json;
1414
using Migration.Common.Log;
1515
using System.Diagnostics;
16+
using static JiraExport.JiraProvider;
1617

1718
namespace JiraExport
1819
{
@@ -81,7 +82,7 @@ private void ExecuteMigration(CommandOption user, CommandOption password, Comman
8182
// where the logs and journal will be saved, logs aid debugging, journal is for recovery of interupted process
8283
string migrationWorkspace = config.Workspace;
8384

84-
var downloadOptions = JiraProvider.DownloadOptions.IncludeParentEpics | JiraProvider.DownloadOptions.IncludeSubItems | JiraProvider.DownloadOptions.IncludeParents;
85+
var downloadOptions = (DownloadOptions)config.DownloadOptions;
8586

8687
var jiraSettings = new JiraSettings(user.Value(), password.Value(), url.Value(), config.SourceProject)
8788
{
@@ -97,9 +98,16 @@ private void ExecuteMigration(CommandOption user, CommandOption password, Comman
9798

9899
BeginSession(configFileName, config, forceFresh, jiraProvider, itemsCount);
99100

100-
// Get the custom field names for epic link field and sprint field
101101
jiraSettings.EpicLinkField = jiraProvider.GetCustomId(config.EpicLinkField);
102+
if(string.IsNullOrEmpty(jiraSettings.EpicLinkField))
103+
{
104+
Logger.Log(LogLevel.Warning, $"Epic link field missing for config field '{config.EpicLinkField}'.");
105+
}
102106
jiraSettings.SprintField = jiraProvider.GetCustomId(config.SprintField);
107+
if (string.IsNullOrEmpty(jiraSettings.SprintField))
108+
{
109+
Logger.Log(LogLevel.Warning, $"Sprint link field missing for config field '{config.SprintField}'.");
110+
}
103111

104112
var mapper = new JiraMapper(jiraProvider, config);
105113
var localProvider = new WiItemProvider(migrationWorkspace);

src/WorkItemMigrator/JiraExport/JiraItem.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,12 @@ private static string[] ParseCustomField(string fieldName, JToken value, JiraPro
383383
public string Key { get { return RemoteIssue.ExValue<string>("$.key"); } }
384384
public string Type { get { return RemoteIssue.ExValue<string>("$.fields.issuetype.name")?.Trim(); } }
385385

386-
public string EpicParent { get { return RemoteIssue.ExValue<string>($"$.fields.{_provider.Settings.EpicLinkField}"); } }
386+
public string EpicParent { get {
387+
if (!string.IsNullOrEmpty(_provider.Settings.EpicLinkField))
388+
return RemoteIssue.ExValue<string>($"$.fields.{_provider.Settings.EpicLinkField}");
389+
else
390+
return null;
391+
} }
387392
public string Parent { get { return RemoteIssue.ExValue<string>("$.fields.parent.key"); } }
388393
public List<string> SubItems { get { return RemoteIssue.SelectTokens("$.fields.subtasks.[*]", false).Select(st => st.ExValue<string>("$.key")).ToList(); } }
389394

src/WorkItemMigrator/JiraExport/JiraProvider.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ public enum DownloadOptions
1818
{
1919
None = 0,
2020
IncludeParentEpics = 1,
21-
IncludeEpicChildren = 2,
22-
IncludeParents = 3,
23-
IncludeSubItems = 4,
24-
IncludeLinkedItems = 5
21+
IncludeParents = 2,
22+
IncludeSubItems = 4
2523
}
2624

2725
readonly Dictionary<string, string> _userEmailCache = new Dictionary<string, string>();
@@ -57,6 +55,7 @@ private static Jira ConnectToJira(JiraSettings jiraSettings)
5755
try
5856
{
5957
Logger.Log(LogLevel.Info, "Connecting to Jira...");
58+
6059
jira = Jira.CreateRestClient(jiraSettings.Url, jiraSettings.UserID, jiraSettings.Pass);
6160
}
6261
catch (Exception ex)

src/WorkItemMigrator/Migration.Common.Log/Logger.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ namespace Migration.Common.Log
1111
{
1212
public enum LogLevel
1313
{
14-
Debug,
15-
Info,
16-
Warning,
17-
Error,
18-
Critical
14+
Debug = 0,
15+
Info = 1,
16+
Warning = 2,
17+
Error = 3,
18+
Critical = 4
1919
}
2020

2121
public static class Logger
@@ -91,18 +91,24 @@ public static void Log(LogLevel level, string message)
9191

9292
if (level == LogLevel.Critical)
9393
{
94-
_errors.Add(message);
94+
if(!_errors.Contains(message))
95+
_errors.Add(message);
96+
9597
Console.Write("Do you want to continue (y/n)? ");
9698
var answer = Console.ReadKey();
9799
if (answer.Key == ConsoleKey.N)
98100
throw new AbortMigrationException(message);
99101
}
100102
else if (level == LogLevel.Error)
101103
{
102-
_errors.Add(message);
104+
if (!_errors.Contains(message))
105+
_errors.Add(message);
103106
}
104-
else if (level == LogLevel.Warning)
107+
else if (level == LogLevel.Warning && !_warnings.Contains(message))
108+
{
105109
_warnings.Add(message);
110+
LogTrace(message, level);
111+
}
106112
}
107113

108114
private static void LogInternal(LogLevel level, string message)
@@ -122,7 +128,13 @@ public static void Log(Exception ex, string message, LogLevel logLevel = LogLeve
122128
Log(logLevel, $"{message + Environment.NewLine}[{ex.GetType().ToString()}] {ex.ToString()}: {Environment.NewLine + ex.StackTrace}");
123129
}
124130

125-
public static void LogEvent(string message, Dictionary<string, string> properties)
131+
private static void LogTrace(string message, LogLevel level)
132+
{
133+
if (_telemetryClient != null)
134+
_telemetryClient.TrackTrace(message, (SeverityLevel)level);
135+
}
136+
137+
private static void LogEvent(string message, Dictionary<string, string> properties)
126138
{
127139
if (_telemetryClient != null)
128140
_telemetryClient.TrackEvent(message, properties);

src/WorkItemMigrator/Migration.Common/Config/ConfigJson.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public class ConfigJson
2323
[JsonProperty(PropertyName = "sprint-field")]
2424
public string SprintField { get; set; } = "Sprint";
2525

26+
[JsonProperty(PropertyName = "download-options")]
27+
public int DownloadOptions { get; set; } = 7; // = All, see DownloadOptions
28+
2629
[JsonProperty(PropertyName = "batch-size")]
2730
public int BatchSize { get; set; } = 20;
2831

src/WorkItemMigrator/WorkItemImport/App.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@
3636
</assemblyBinding>
3737
</runtime>
3838
<appSettings>
39-
<add key="applicationInsightsKey" value="__APP_INSIGHTS_KEY__" />
39+
<add key="applicationInsightsKey" value="584b887e-5d80-41c3-8303-9f421d46c421" />
4040
</appSettings>
4141
</configuration>

0 commit comments

Comments
 (0)