Repository: microsoft/onefuzz
File: src/ApiService/ApiService/onefuzzlib/notifications/Ado.cs (C#)

Code before:
                }
            } else if (numNonDuplicate == 1) {
                await UpdateExisting(await nonDuplicate.SingleAsync(), notificationInfo);
            }
              // We have matching work items but all are duplicates
              else if (await matchingWorkItems.AnyAsync()) {
                _logTracer.WithTags(notificationInfo).Info($"All matching work items were duplicates, re-opening the oldest one");
                var oldestWorkItem = await matchingWorkItems.OrderBy(wi => wi.Id).FirstAsync();
                await UpdateExisting(oldestWorkItem, notificationInfo);

                _ = await _client.AddCommentAsync(
                    new CommentCreate() {
                        Text = "This work item was re-opened because OneFuzz could only find related work items that are marked as duplicate."
                    },
                    _project,
                    (int)oldestWorkItem.Id!);
            }
              // We never saw a work item like this before, it must be new
              else {
                var entry = await CreateNew();
                var adoEventType = "AdoNewItem";
                _logTracer.WithTags(notificationInfo).Event($"{adoEventType} {entry.Id:Tag:WorkItemId}");
            }
        }

        private static bool IsDuplicate(WorkItem wi) {
            // A work item could have System.State == Resolve && System.Reason == Duplicate
            // OR it could have System.State == Closed && System.Reason == Duplicate
            // I haven't found any other combinations where System.Reason could be duplicate but just to be safe
            // we're explicitly _not_ checking the state of the work item to determine if it's duplicate
            return (wi.Fields.ContainsKey("System.Reason") && string.Equals(wi.Fields["System.Reason"].ToString(), "Duplicate"))
            // Alternatively, the work item can also specify a 'relation' to another work item.
            // This is typically used to create parent/child relationships between work items but can also
            // Be used to mark duplicates so we should check this as well.
            // ADO has 2 relation types relating to duplicates: "Duplicate" and  "Duplicate Of"
            // When work item A has a link type "Duplicate" to work item B, B automatically gains a link type "Duplicate Of" pointing to A
            // It's my understanding that the work item containing the "Duplicate" link should be the original while work items containing
            // "Duplicate Of" are the duplicates. That is why we search for the relation type "Duplicate Of".
            // "Duplicate Of" has the relation type: "System.LinkTypes.Duplicate-Forward"
            // Source: https://learn.microsoft.com/en-us/azure/devops/boards/queries/link-type-reference?view=azure-devops#work-link-types
            || (wi.Relations != null && wi.Relations.Any(relation => string.Equals(relation.Rel, "System.LinkTypes.Duplicate-Forward")));
        }
    }
}


Review comment (refactor):
I suggest renaming this to something like `IsADODuplicate` (and the associated variables) to avoid confusion with what we call duplicate in the template. Ideally we should change the template itself to rename `onDuplicate` to `onExisting` but that would cause some backward compat issues.

Code after:
                }
            } else if (numNonDuplicateWorkItems == 1) {
                await UpdateExisting(await nonDuplicateWorkItems.SingleAsync(), notificationInfo);
            }
              // We have matching work items but all are duplicates
              else if (await matchingWorkItems.AnyAsync()) {
                _logTracer.WithTags(notificationInfo).Info($"All matching work items were duplicates, re-opening the oldest one");
                var oldestWorkItem = await matchingWorkItems.OrderBy(wi => wi.Id).FirstAsync();
                await UpdateExisting(oldestWorkItem, notificationInfo);

                _ = await _client.AddCommentAsync(
                    new CommentCreate() {
                        Text = "This work item was re-opened because OneFuzz could only find related work items that are marked as duplicate."
                    },
                    _project,
                    (int)oldestWorkItem.Id!);
            }
              // We never saw a work item like this before, it must be new
              else {
                var entry = await CreateNew();
                var adoEventType = "AdoNewItem";
                _logTracer.WithTags(notificationInfo).Event($"{adoEventType} {entry.Id:Tag:WorkItemId}");
            }
        }

        private static bool IsADODuplicateWorkItem(WorkItem wi) {
            // A work item could have System.State == Resolve && System.Reason == Duplicate
            // OR it could have System.State == Closed && System.Reason == Duplicate
            // I haven't found any other combinations where System.Reason could be duplicate but just to be safe
            // we're explicitly _not_ checking the state of the work item to determine if it's duplicate
            return (wi.Fields.ContainsKey("System.Reason") && string.Equals(wi.Fields["System.Reason"].ToString(), "Duplicate"))
            // Alternatively, the work item can also specify a 'relation' to another work item.
            // This is typically used to create parent/child relationships between work items but can also
            // Be used to mark duplicates so we should check this as well.
            // ADO has 2 relation types relating to duplicates: "Duplicate" and  "Duplicate Of"
            // When work item A has a link type "Duplicate" to work item B, B automatically gains a link type "Duplicate Of" pointing to A
            // It's my understanding that the work item containing the "Duplicate" link should be the original while work items containing
            // "Duplicate Of" are the duplicates. That is why we search for the relation type "Duplicate Of".
            // "Duplicate Of" has the relation type: "System.LinkTypes.Duplicate-Forward"
            // Source: https://learn.microsoft.com/en-us/azure/devops/boards/queries/link-type-reference?view=azure-devops#work-link-types
            || (wi.Relations != null && wi.Relations.Any(relation => string.Equals(relation.Rel, "System.LinkTypes.Duplicate-Forward")));
        }
    }
}