Skip to content

Commit 9547cf0

Browse files
Merge pull request #1108 from solidify/feature/expose-revision-defer-as-config-parameter
Expose config parameter: DeferForRevisionsSucceedingAttachmentImportsMilliseconds
2 parents 3d17927 + fb381ff commit 9547cf0

File tree

8 files changed

+34
-11
lines changed

8 files changed

+34
-11
lines changed

docs/config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ The migration configuration file is defined in a json file with the properties d
3838
|**suppress-notifications**|False|boolean|Set to True to suppress all notifications in Azure DevOps about created and updated Work Items. Default = False.|
3939
|**include-development-links**|False|boolean|Set to True to migrated commit links from Jira to Azure DevOps. You will also need to fill out the **repository-map** property. Default = False.|
4040
|**sleep-time-between-revision-import-milliseconds**|False|integer|How many milliseconds to sleep between each revision import. Use this if throttling is an issue for ADO Services. Default = 0 (no sleep).|
41+
|**buffer-revisions-succeeding-attachment-imports-milliseconds**|False|integer|How many milliseconds to buffer each subsequent revision if there is a negative revision timestamp offset. Increase this if you get problems with VS402625 error messages. Default = 5 (ms).|
4142
|**process-template**|False|string|Process template in the target DevOps project. Supported values: Scrum, Agile or CMMI. Default = "Scrum".|
4243
|**link-map**|True|json|List of **links** to map between Jira and Azure DevOps/TFS work item link types.|
4344
|**type-map**|True|json|List of the work item **types** you want to migrate from Jira to Azure DevOps/TFS.|

docs/faq.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,26 @@ curl -D-
430430
"http://johnie:8081/rest/api/2/search"
431431
```
432432

433-
## 19. Sprint names are corrupted. ADO Iteration paths are named "[ synced = false ]"
433+
## 19. I get the error message "VS402625: Dates must be increasing with each revision."
434+
435+
ADO can sometimes add a few milliseconds to the work item changedDate when adding an attachment. This can have unfortunate consequences if the tool attempts to import a subsequent revision with a changedDate that is less than the previous reivison that was successfully imported.
436+
437+
You may end up receiving an error message similar to this one:
438+
439+
```txt
440+
[E][18:32:06] VS402625: Dates must be increasing with each revision.
441+
[E][18:32:06] Work Item 15312 failed to save.
442+
```
443+
444+
The solution is to buffer the subsequent revision's changedDate by a few miliseconds. This is the purpose of the configuration parameter `buffer-revisions-succeeding-attachment-imports-milliseconds` (default: 5). Add this parameter to your `config.json` file and try increasing the value by 1 (5, 6, 7, and so on...) until the import succeeds without errors.
445+
446+
Example `config.json`:
447+
448+
```json
449+
"buffer-revisions-succeeding-attachment-imports-milliseconds": 6,
450+
```
451+
452+
## 20. Sprint names are corrupted. ADO Iteration paths are named "[ synced = false ]"
434453

435454
The issue is usually that a custom field has been defined in Jira which is also named "Sprint", and the tool is picking up this field instead of the default Srpint field.
436455

@@ -458,9 +477,7 @@ It could be worth trying this mapping when running against Jira Cloud too:
458477

459478
It seems that for jira server, the field IDs can different between different developer instances. You can use the Get Fields endpoint to find out which field ID (customfield_xxxxx) is used by Sprint in your instance: https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#about
460479

461-
Give it a try and let me know if it still does not work.
462-
463-
## 20. Azure DevOps Rate and usage limits (ADO Cloud only)
480+
## 21. Azure DevOps Rate and usage limits (ADO Cloud only)
464481

465482
In the unlikely event that you experience issues with being rate limited by Azure DevOps, we always recommend the following procedure:
466483

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ public class ConfigJson
8181
[JsonProperty(PropertyName = "include-jira-css-styles")]
8282
public bool IncludeJiraCssStyles { get; set; } = false;
8383

84+
[JsonProperty(PropertyName = "buffer-revisions-succeeding-attachment-imports-milliseconds")]
85+
public int BufferRevisionsSucceedingAttachmentImportsMilliseconds { get; set; } = 5;
86+
8487
[JsonProperty(PropertyName = "ignore-empty-revisions")]
8588
public bool IgnoreEmptyRevisions { get; set; } = false;
8689

src/WorkItemMigrator/WorkItemImport/Agent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public bool ImportRevision(WiRevision rev, WorkItem wi, Settings settings)
6767
if (rev.Index == 0)
6868
_witClientUtils.EnsureClassificationFields(rev);
6969

70-
_witClientUtils.EnsureDateFields(rev, wi);
70+
_witClientUtils.EnsureDateFields(rev, wi, settings.BufferRevisionsSucceedingAttachmentImportsMilliseconds);
7171
_witClientUtils.EnsureAuthorFields(rev);
7272
_witClientUtils.EnsureAssigneeField(rev, wi);
7373
_witClientUtils.EnsureFieldsOnStateChange(rev, wi);

src/WorkItemMigrator/WorkItemImport/ImportCommandLine.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ private bool ExecuteMigration(CommandOption token, CommandOption url, CommandOpt
9393
IncludeLinkComments = config.IncludeLinkComments,
9494
IncludeDevelopmentLinks = config.IncludeDevelopmentLinks,
9595
FieldMap = config.FieldMap,
96-
SuppressNotifications = config.SuppressNotifications
96+
SuppressNotifications = config.SuppressNotifications,
97+
BufferRevisionsSucceedingAttachmentImportsMilliseconds = config.BufferRevisionsSucceedingAttachmentImportsMilliseconds
9798
};
9899

99100
// initialize Azure DevOps/TFS connection. Creates/fetches project, fills area and iteration caches.

src/WorkItemMigrator/WorkItemImport/Settings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ public Settings(string account, string project, string pat)
2222
public bool IncludeDevelopmentLinks { get; internal set; }
2323
public FieldMap FieldMap { get; internal set; }
2424
public bool SuppressNotifications { get; internal set; }
25+
public int BufferRevisionsSucceedingAttachmentImportsMilliseconds { get; set; }
2526
}
2627
}

src/WorkItemMigrator/WorkItemImport/WitClient/WitClientUtils.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ public void EnsureAssigneeField(WiRevision rev, WorkItem wi)
240240
rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.AssignedTo, Value = assignedTo });
241241
}
242242

243-
public void EnsureDateFields(WiRevision rev, WorkItem wi)
243+
public void EnsureDateFields(WiRevision rev, WorkItem wi, int bufferMS)
244244
{
245245
if (rev == null)
246246
{
@@ -271,8 +271,8 @@ public void EnsureDateFields(WiRevision rev, WorkItem wi)
271271
else
272272
{
273273
// ADO can add a few milliseconds to work item createdDate when adding an attachment, hence adding more here to the revision time
274-
rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ChangedDate, Value = rev.Time.AddMilliseconds(5).ToString("o") });
275-
wi.Fields[WiFieldReference.ChangedDate] = rev.Time.AddMilliseconds(5);
274+
rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ChangedDate, Value = rev.Time.AddMilliseconds(bufferMS).ToString("o") });
275+
wi.Fields[WiFieldReference.ChangedDate] = rev.Time.AddMilliseconds(bufferMS);
276276
}
277277
}
278278

src/WorkItemMigrator/tests/Migration.Wi-Import.Tests/WitClient/WitClientUtilsTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ public void When_calling_ensure_date_fields_with_empty_args_Then_an_exception_is
280280
MockedWitClientWrapper witClientWrapper = new MockedWitClientWrapper();
281281
WitClientUtils wiUtils = new WitClientUtils(witClientWrapper);
282282
Assert.That(
283-
() => wiUtils.EnsureDateFields(null, null),
283+
() => wiUtils.EnsureDateFields(null, null, 0),
284284
Throws.InstanceOf<ArgumentException>());
285285
}
286286

@@ -303,7 +303,7 @@ public void When_calling_ensure_date_fields_with_first_revision_Then_dates_are_a
303303

304304
createdWI.Fields[WiFieldReference.ChangedDate] = now;
305305

306-
wiUtils.EnsureDateFields(rev, createdWI);
306+
wiUtils.EnsureDateFields(rev, createdWI, 0);
307307

308308
Assert.Multiple(() =>
309309
{

0 commit comments

Comments
 (0)