ADO
This commit is contained in:
@ -1,24 +1,13 @@
|
||||
using Adaptation.FileHandlers.ConvertExcelToJson;
|
||||
using Adaptation.FileHandlers.json.WorkItems;
|
||||
using Adaptation.Shared;
|
||||
using Adaptation.Shared.Duplicator;
|
||||
using Adaptation.Shared.Methods;
|
||||
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
|
||||
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
|
||||
using Microsoft.VisualStudio.Services.WebApi.Patch;
|
||||
using Microsoft.VisualStudio.Services.WebApi.Patch.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Adaptation.FileHandlers.json;
|
||||
|
||||
@ -47,21 +36,7 @@ public class ProcessData : IProcessData
|
||||
{
|
||||
fileInfoCollection.Clear();
|
||||
_Details = new List<object>();
|
||||
Parse(fileRead,
|
||||
logistics,
|
||||
fileInfoCollection,
|
||||
httpClient,
|
||||
basePage,
|
||||
api,
|
||||
query,
|
||||
workItemTrackingHttpClient,
|
||||
project,
|
||||
assignedToNameToEncodedPAT,
|
||||
assignedToNameToUser,
|
||||
requestorNameToUser,
|
||||
json,
|
||||
forceUpdatedBy,
|
||||
forceDeleteUpdatedBy);
|
||||
Parse();
|
||||
}
|
||||
|
||||
string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary<string, string> reactors) =>
|
||||
@ -73,724 +48,7 @@ public class ProcessData : IProcessData
|
||||
internal static List<Description> GetDescriptions(JsonElement[] jsonElements) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
#nullable enable
|
||||
|
||||
private static void KillTime(int loops)
|
||||
{
|
||||
for (int i = 1; i < loops; i++)
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
private static void AddPatch(JsonPatchDocument document, string path, object value) =>
|
||||
document.Add(new JsonPatchOperation { From = null, Operation = Operation.Add, Path = path, Value = value });
|
||||
|
||||
private static Dictionary<string, FIBacklogMesa> GetFIBacklogMesaCollection(string json)
|
||||
{
|
||||
Dictionary<string, FIBacklogMesa> results = new();
|
||||
string key;
|
||||
FIBacklogMesa[]? fiBacklogMesaCollection;
|
||||
fiBacklogMesaCollection = JsonSerializer.Deserialize<FIBacklogMesa[]>(json, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
|
||||
if (fiBacklogMesaCollection is null || fiBacklogMesaCollection.Length == 0)
|
||||
throw new NullReferenceException();
|
||||
foreach (FIBacklogMesa fiBacklogMesa in fiBacklogMesaCollection)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.Req))
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.Submitted))
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.Requestor))
|
||||
continue;
|
||||
key = $"{fiBacklogMesa.Req} - ";
|
||||
if (results.ContainsKey(key))
|
||||
continue;
|
||||
results.Add(key, fiBacklogMesa);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static string GetIds(HttpClient httpClient, string basePage, string api, string query)
|
||||
{
|
||||
StringBuilder result = new();
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.GetAsync(string.Concat(basePage, api, query));
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<Stream> streamTask = httpResponseMessageTask.Result.Content.ReadAsStreamAsync();
|
||||
streamTask.Wait();
|
||||
if (!streamTask.Result.CanRead)
|
||||
throw new NullReferenceException(nameof(streamTask));
|
||||
WIQL.Root? root = JsonSerializer.Deserialize<WIQL.Root>(streamTask.Result, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
|
||||
streamTask.Result.Dispose();
|
||||
if (root is null || root.WorkItems is null)
|
||||
throw new NullReferenceException(nameof(root));
|
||||
foreach (WIQL.WorkItem workItem in root.WorkItems)
|
||||
_ = result.Append(workItem.Id).Append(',');
|
||||
if (result.Length > 0)
|
||||
_ = result.Remove(result.Length - 1, 1);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private static Value[] GetWorkItems(IFileRead fileRead, HttpClient httpClient, string basePage, string api, string ids)
|
||||
{
|
||||
Value[]? results;
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.GetAsync(string.Concat(basePage, api, $"/workitems?ids={ids}"));
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<Stream> streamTask = httpResponseMessageTask.Result.Content.ReadAsStreamAsync();
|
||||
streamTask.Wait();
|
||||
if (!streamTask.Result.CanRead)
|
||||
throw new NullReferenceException(nameof(streamTask));
|
||||
JsonElement? jsonElement = JsonSerializer.Deserialize<JsonElement>(streamTask.Result);
|
||||
if (jsonElement is null || jsonElement.Value.ValueKind != JsonValueKind.Object)
|
||||
throw new NullReferenceException(nameof(jsonElement));
|
||||
if (!fileRead.IsEAFHosted)
|
||||
File.WriteAllText("../../example.json", jsonElement.Value.EnumerateObject().Last().Value.ToString());
|
||||
results = JsonSerializer.Deserialize<Value[]>(jsonElement.Value.EnumerateObject().Last().Value);
|
||||
if (results is null || results.Length == 0)
|
||||
throw new NullReferenceException(nameof(results));
|
||||
return results;
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<ValueWithReq> GetValueWithReqCollection(IReadOnlyList<Value> workItems)
|
||||
{
|
||||
List<ValueWithReq> results = new();
|
||||
string[] segments;
|
||||
foreach (Value value in workItems)
|
||||
{
|
||||
segments = value.Fields.SystemTitle.Split('-');
|
||||
if (segments.Length < 2)
|
||||
continue;
|
||||
if (!int.TryParse(segments[0], out int req) || req == 0)
|
||||
continue;
|
||||
results.Add(new(value, req));
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<ValueWithReq> RemoveFrom(Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa, ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
||||
{
|
||||
List<ValueWithReq> results = new();
|
||||
foreach (ValueWithReq valueWithReq in valueWithReqCollection)
|
||||
{
|
||||
if (keyToFIBacklogMesa.Remove($"{valueWithReq.Req} - "))
|
||||
continue;
|
||||
results.Add(valueWithReq);
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static void Update(WorkItemTrackingHttpClient workItemTrackingHttpClient, string sync, ValueWithReq valueWithReq)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
AddPatch(result, "/fields/System.Tags", sync);
|
||||
Task<WorkItem> workItem = workItemTrackingHttpClient.UpdateWorkItemAsync(result, valueWithReq.Value.Id);
|
||||
workItem.Wait();
|
||||
}
|
||||
|
||||
private static DateTime? GetCommitDate(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
DateTime? result;
|
||||
DateTime dateTime;
|
||||
DateTime minDateTime = DateTime.MinValue.AddYears(10);
|
||||
string commitDate = fiBacklogMesa.CommitDate.Split(' ')[0];
|
||||
if (string.IsNullOrEmpty(commitDate))
|
||||
result = null;
|
||||
else
|
||||
{
|
||||
if (DateTime.TryParseExact(commitDate, "MM/dd/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime) && dateTime >= minDateTime)
|
||||
result = dateTime.AddHours(12).ToUniversalTime();
|
||||
else
|
||||
{
|
||||
if (DateTime.TryParseExact(commitDate, "dd-MMM-yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime) && dateTime >= minDateTime)
|
||||
result = dateTime.AddHours(12).ToUniversalTime();
|
||||
else
|
||||
{
|
||||
if (DateTime.TryParse(commitDate, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime) && dateTime >= minDateTime)
|
||||
result = dateTime.AddHours(12).ToUniversalTime();
|
||||
else
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int GetPriority(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
int result;
|
||||
if (!int.TryParse(fiBacklogMesa.Priority.Substring(0, 1), out int priority) || priority == 0 || priority > 3)
|
||||
result = 4;
|
||||
else
|
||||
result = priority;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetTitle(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
string result = $"{fiBacklogMesa.Req} - {fiBacklogMesa.Subject.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[0]}";
|
||||
if (result.Length > 128)
|
||||
result = result.Substring(0, 127);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetTitle(FIBacklogMesa fiBacklogMesa, ValueWithReq valueWithReq)
|
||||
{
|
||||
string result = $"{valueWithReq.Req} - {fiBacklogMesa.Subject.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[0]}";
|
||||
if (result.Length > 128)
|
||||
result = result.Substring(0, 127);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string? GetMappedState(FIBacklogMesa fiBacklogMesa) =>
|
||||
fiBacklogMesa.Status == "CMP" ? "Closed" : fiBacklogMesa.Status == "UAT" ? "Resolved" : fiBacklogMesa.Status == "In process" ? "Active" : null;
|
||||
|
||||
private static void SetSyncTag(WorkItemTrackingHttpClient workItemTrackingHttpClient, ReadOnlyDictionary<string, string> requestorNameToUser, Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa, ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
||||
{
|
||||
string key;
|
||||
string title;
|
||||
int priority;
|
||||
bool isBugFix;
|
||||
string? state;
|
||||
List<string> tags;
|
||||
TimeSpan timeSpan;
|
||||
DateTime? dateTime;
|
||||
List<string> compareTags;
|
||||
const string sync = "Sync";
|
||||
FIBacklogMesa? fiBacklogMesa;
|
||||
foreach (ValueWithReq valueWithReq in valueWithReqCollection)
|
||||
{
|
||||
key = $"{valueWithReq.Req} - ";
|
||||
compareTags = GetTags(valueWithReq.Value.Fields);
|
||||
if (compareTags.Contains(sync))
|
||||
continue;
|
||||
if (!keyToFIBacklogMesa.TryGetValue(key, out fiBacklogMesa))
|
||||
continue;
|
||||
tags = GetTags(fiBacklogMesa);
|
||||
title = GetTitle(fiBacklogMesa, valueWithReq);
|
||||
isBugFix = fiBacklogMesa.Priority == "0 - BugFix";
|
||||
_ = requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser);
|
||||
if (!string.IsNullOrEmpty(requestorUser) && (valueWithReq.Value.Fields.SystemAssignedTo is null || !valueWithReq.Value.Fields.SystemAssignedTo.UniqueName.Equals(requestorUser, StringComparison.CurrentCultureIgnoreCase)))
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if (valueWithReq.Value.Fields.SystemTitle != title)
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.Definition) && valueWithReq.Value.Fields.SystemDescription != fiBacklogMesa.Definition.Replace("&", "&").Replace("\"", """))
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
foreach (string tag in tags)
|
||||
{
|
||||
if (compareTags.Contains(tag))
|
||||
continue;
|
||||
_ = tags.Remove(tag);
|
||||
break;
|
||||
}
|
||||
if (tags.Count != compareTags.Count)
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if ((isBugFix && valueWithReq.Value.Fields.SystemWorkItemType != "Bug") || (!isBugFix && valueWithReq.Value.Fields.SystemWorkItemType == "Bug"))
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if (!isBugFix)
|
||||
{
|
||||
priority = GetPriority(fiBacklogMesa);
|
||||
if (valueWithReq.Value.Fields.MicrosoftVSTSCommonPriority != priority)
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
state = GetMappedState(fiBacklogMesa);
|
||||
if (!string.IsNullOrEmpty(state) && valueWithReq.Value.Fields.SystemState != state)
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
if (!isBugFix && int.TryParse(fiBacklogMesa.EstEffortDays, out int estEffortDays) && valueWithReq.Value.Fields.Effort != estEffortDays)
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
dateTime = GetCommitDate(fiBacklogMesa);
|
||||
if (dateTime is not null)
|
||||
{
|
||||
timeSpan = new(valueWithReq.Value.Fields.TargetDate.Ticks - dateTime.Value.Ticks);
|
||||
if (timeSpan.Hours is > 32 or < -32)
|
||||
{
|
||||
Update(workItemTrackingHttpClient, sync, valueWithReq);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, List<int>> GetForceUpdatedByCollection(ReadOnlyDictionary<string, string> assignedToNameToEncodedPAT, ReadOnlyDictionary<string, string> assignedToNameToUser, Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa, ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
||||
{
|
||||
Dictionary<string, List<int>> results = new();
|
||||
string key;
|
||||
List<int>? reqCollection;
|
||||
FIBacklogMesa? fiBacklogMesa;
|
||||
foreach (ValueWithReq valueWithReq in valueWithReqCollection)
|
||||
{
|
||||
key = $"{valueWithReq.Req} - ";
|
||||
if (!keyToFIBacklogMesa.TryGetValue(key, out fiBacklogMesa))
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.AssignedTo))
|
||||
continue;
|
||||
if (!assignedToNameToUser.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToUser))
|
||||
continue;
|
||||
if (!valueWithReq.Value.Fields.SystemChangedBy.UniqueName.Equals(assignedToUser, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
if (!assignedToNameToEncodedPAT.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToEncodedPAT) || assignedToEncodedPAT.Length < 15)
|
||||
continue;
|
||||
if (!results.TryGetValue(assignedToEncodedPAT, out reqCollection))
|
||||
{
|
||||
results.Add(assignedToEncodedPAT, new());
|
||||
if (!results.TryGetValue(assignedToEncodedPAT, out reqCollection))
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
reqCollection.Add(valueWithReq.Value.Id);
|
||||
}
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, List<int[]>> GetForceUpdatedByCollectionDelete(string forceUpdatedByComment, ReadOnlyDictionary<string, string> assignedToNameToEncodedPAT, ReadOnlyDictionary<string, string> assignedToNameToUser, Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa, ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
||||
{
|
||||
Dictionary<string, List<int[]>> results = new();
|
||||
string key;
|
||||
List<int[]>? reqCollection;
|
||||
FIBacklogMesa? fiBacklogMesa;
|
||||
foreach (ValueWithReq valueWithReq in valueWithReqCollection)
|
||||
{
|
||||
key = $"{valueWithReq.Req} - ";
|
||||
if (!keyToFIBacklogMesa.TryGetValue(key, out fiBacklogMesa))
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(fiBacklogMesa.AssignedTo))
|
||||
continue;
|
||||
if (!assignedToNameToUser.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToUser))
|
||||
continue;
|
||||
if (valueWithReq.Value.Fields.SystemHistory == forceUpdatedByComment)
|
||||
{
|
||||
if (!assignedToNameToEncodedPAT.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToEncodedPAT) || assignedToEncodedPAT.Length < 15)
|
||||
continue;
|
||||
if (!results.TryGetValue(assignedToEncodedPAT, out reqCollection))
|
||||
{
|
||||
results.Add(assignedToEncodedPAT, new());
|
||||
if (!results.TryGetValue(assignedToEncodedPAT, out reqCollection))
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
reqCollection.Add(new int[] { valueWithReq.Value.Id, valueWithReq.Value.CommentVersionRef.CommentId });
|
||||
}
|
||||
}
|
||||
return new(results);
|
||||
}
|
||||
|
||||
private static void Post(HttpClient httpClient, string basePage, string api, string query, HttpContent httpContent)
|
||||
{
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.PostAsync(string.Concat(basePage, api, query), httpContent);
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<string> stringTask = httpResponseMessageTask.Result.Content.ReadAsStringAsync();
|
||||
stringTask.Wait();
|
||||
KillTime(30);
|
||||
}
|
||||
|
||||
private static void ForceUpdatedBy(HttpClient httpClient, string basePage, string project, string api, string forceUpdatedByComment, ReadOnlyDictionary<string, List<int>> updateCollection)
|
||||
{
|
||||
string stringPayload;
|
||||
HttpContent httpContent;
|
||||
HttpClient keyHttpClient;
|
||||
AuthenticationHeaderValue authenticationHeaderValue;
|
||||
foreach (KeyValuePair<string, List<int>> keyValuePair in updateCollection)
|
||||
{
|
||||
keyHttpClient = new() { BaseAddress = httpClient.BaseAddress };
|
||||
authenticationHeaderValue = keyHttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", keyValuePair.Key);
|
||||
if (authenticationHeaderValue.Parameter != keyValuePair.Key)
|
||||
throw new NotSupportedException();
|
||||
foreach (int id in keyValuePair.Value)
|
||||
{
|
||||
stringPayload = JsonSerializer.Serialize(new { text = forceUpdatedByComment });
|
||||
httpContent = new StringContent($"{stringPayload}", Encoding.UTF8, "application/json");
|
||||
Post(keyHttpClient, $"{basePage}/{project}", api, $"/workitems/{id}/comments?api-version=5.1-preview.3", httpContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Delete(HttpClient httpClient, string basePage, string api, string query)
|
||||
{
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.DeleteAsync(string.Concat(basePage, api, query));
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<string> stringTask = httpResponseMessageTask.Result.Content.ReadAsStringAsync();
|
||||
stringTask.Wait();
|
||||
KillTime(30);
|
||||
}
|
||||
|
||||
private static void ForceUpdatedByDelete(HttpClient httpClient, string basePage, string project, string api, ReadOnlyDictionary<string, List<int[]>> deleteCollection)
|
||||
{
|
||||
HttpClient keyHttpClient;
|
||||
AuthenticationHeaderValue authenticationHeaderValue;
|
||||
foreach (KeyValuePair<string, List<int[]>> keyValuePair in deleteCollection)
|
||||
{
|
||||
keyHttpClient = new() { BaseAddress = httpClient.BaseAddress };
|
||||
authenticationHeaderValue = keyHttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", keyValuePair.Key);
|
||||
if (authenticationHeaderValue.Parameter != keyValuePair.Key)
|
||||
throw new NotSupportedException();
|
||||
foreach (int[] idCollection in keyValuePair.Value)
|
||||
{
|
||||
if (idCollection.Length != 2)
|
||||
throw new NotSupportedException();
|
||||
Delete(keyHttpClient, $"{basePage}/{project}", api, $"/workitems/{idCollection[0]}/comments/{idCollection[1]}?api-version=7.0-preview.3");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDescription(FIBacklogMesa fiBacklogMesa, DateTime dateTime) =>
|
||||
$"Req:{fiBacklogMesa.Req}; Submitted:{(dateTime == DateTime.MinValue ? fiBacklogMesa.Submitted : dateTime.ToString("d-MMM-yy"))}; Requestor:{fiBacklogMesa.Requestor}; AssignedTo:{fiBacklogMesa.AssignedTo}; SecondResource:{fiBacklogMesa.SecondResource}; Systems:{fiBacklogMesa.SystemS}; ";
|
||||
|
||||
private static void Update(HttpClient httpClient, string basePage, string api, string query, HttpContent httpContent)
|
||||
{
|
||||
#if Windows
|
||||
Task<HttpResponseMessage> httpResponseMessageTask = httpClient.PatchAsync(string.Concat(basePage, api, query), httpContent);
|
||||
httpResponseMessageTask.Wait();
|
||||
if (!httpResponseMessageTask.Result.IsSuccessStatusCode)
|
||||
throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString());
|
||||
Task<string> stringTask = httpResponseMessageTask.Result.Content.ReadAsStringAsync();
|
||||
stringTask.Wait();
|
||||
#endif
|
||||
KillTime(30);
|
||||
}
|
||||
|
||||
private static void UpdateIds(HttpClient httpClient, string basePage, string api, string[] checkFiles)
|
||||
{
|
||||
int? idIndex;
|
||||
string[] lines;
|
||||
string[] segments;
|
||||
string stringPayload;
|
||||
HttpContent httpContent;
|
||||
foreach (string checkFile in checkFiles)
|
||||
{
|
||||
idIndex = null;
|
||||
lines = File.ReadAllLines(checkFile);
|
||||
if (lines.Length < 1)
|
||||
continue;
|
||||
segments = lines.First().Split(',');
|
||||
for (int i = 0; i < segments.Length; i++)
|
||||
{
|
||||
if (segments[i] == "ID")
|
||||
{
|
||||
idIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idIndex is null)
|
||||
continue;
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
segments = lines[i].Split(',');
|
||||
if (segments.Length < idIndex.Value)
|
||||
continue;
|
||||
var payload = new
|
||||
{
|
||||
op = "replace",
|
||||
path = "/fields/System.IterationPath",
|
||||
value = "Mesa_FI"
|
||||
};
|
||||
stringPayload = JsonSerializer.Serialize(payload);
|
||||
httpContent = new StringContent($"[{stringPayload}]", Encoding.UTF8, "application/json-patch+json");
|
||||
Update(httpClient, basePage, api, $"/workitems/{segments[idIndex.Value].Replace("\"", string.Empty)}?api-version=1.0", httpContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetUATDocument(string project, ReadOnlyDictionary<string, string> requestorNameToUser, DateTime dateTime, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
AddPatch(result, "/fields/System.AreaPath", project);
|
||||
string description = GetDescription(fiBacklogMesa, dateTime);
|
||||
AddPatch(result, "/fields/System.IterationPath", project);
|
||||
AddPatch(result, "/fields/System.Title", $"{fiBacklogMesa.Req} - UAT");
|
||||
AddPatch(result, "/fields/System.Description", description);
|
||||
if (requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", requestorUser);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetBugDocument(string project, ReadOnlyDictionary<string, string> assignedToNameToUser, Task<WorkItem> uatWorkItemTask, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
if (uatWorkItemTask.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
string title = GetTitle(fiBacklogMesa);
|
||||
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = uatWorkItemTask.Result.Url });
|
||||
AddPatch(result, "/fields/System.AreaPath", project);
|
||||
AddPatch(result, "/fields/System.IterationPath", project);
|
||||
AddPatch(result, "/fields/System.Title", title);
|
||||
string? state = GetMappedState(fiBacklogMesa);
|
||||
if (!string.IsNullOrEmpty(state))
|
||||
AddPatch(result, "/fields/System.State", state);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.Definition))
|
||||
AddPatch(result, "/fields/System.Description", fiBacklogMesa.Definition);
|
||||
if (assignedToNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", requestorUser);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetDeveloperTaskDocument(string project, ReadOnlyDictionary<string, string> assignedToNameToUser, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
AddPatch(result, "/fields/System.AreaPath", project);
|
||||
AddPatch(result, "/fields/System.IterationPath", project);
|
||||
AddPatch(result, "/fields/System.Title", $"{fiBacklogMesa.Req} - Developer Task");
|
||||
if (assignedToNameToUser.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", assignedToUser);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetSecondDeveloperTaskDocument(string project, ReadOnlyDictionary<string, string> assignedToNameToUser, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
AddPatch(result, "/fields/System.AreaPath", project);
|
||||
AddPatch(result, "/fields/System.IterationPath", project);
|
||||
AddPatch(result, "/fields/System.Title", $"{fiBacklogMesa.Req} - Developer Task");
|
||||
if (assignedToNameToUser.TryGetValue(fiBacklogMesa.SecondResource, out string? secondResourceUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", secondResourceUser);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetUserStoryDocument(string project, ReadOnlyDictionary<string, string> requestorNameToUser, Task<WorkItem> uatWorkItemTask, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
if (uatWorkItemTask?.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = uatWorkItemTask.Result.Url });
|
||||
AddPatch(result, "/fields/System.AreaPath", project);
|
||||
AddPatch(result, "/fields/System.IterationPath", project);
|
||||
AddPatch(result, "/fields/System.Title", $"{fiBacklogMesa.Req} - User Story");
|
||||
string? state = GetMappedState(fiBacklogMesa);
|
||||
if (!string.IsNullOrEmpty(state))
|
||||
AddPatch(result, "/fields/System.State", state);
|
||||
if (requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", requestorUser);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetAssignedToRelationDocument(Task<WorkItem> assignedToWorkItemTask)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
if (assignedToWorkItemTask.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = assignedToWorkItemTask.Result.Url });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetSecondResourceDocument(Task<WorkItem> secondResourceWorkItemTask)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
if (secondResourceWorkItemTask?.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = secondResourceWorkItemTask.Result.Url });
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JsonPatchDocument GetFeatureDocument(string project, ReadOnlyDictionary<string, string> requestorNameToUser, List<string> tags, Task<WorkItem>? userStoryWorkItemTask, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
JsonPatchDocument result = new();
|
||||
if (userStoryWorkItemTask?.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
string title = GetTitle(fiBacklogMesa);
|
||||
int priority = GetPriority(fiBacklogMesa);
|
||||
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = userStoryWorkItemTask.Result.Url });
|
||||
AddPatch(result, "/fields/System.AreaPath", project);
|
||||
if (tags.Count > 0)
|
||||
{
|
||||
AddPatch(result, "/fields/System.Tags", tags.Last());
|
||||
tags.RemoveAt(tags.Count - 1);
|
||||
}
|
||||
AddPatch(result, "/fields/System.IterationPath", project);
|
||||
AddPatch(result, "/fields/Microsoft.VSTS.Common.Priority", priority);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.Definition))
|
||||
AddPatch(result, "/fields/System.Description", fiBacklogMesa.Definition);
|
||||
string? state = GetMappedState(fiBacklogMesa);
|
||||
if (!string.IsNullOrEmpty(state))
|
||||
AddPatch(result, "/fields/System.State", state);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.EstEffortDays) && int.TryParse(fiBacklogMesa.EstEffortDays, out int estEffortDays) && estEffortDays != 0)
|
||||
AddPatch(result, "/fields/Microsoft.VSTS.Scheduling.Effort", estEffortDays);
|
||||
DateTime? dateTime = GetCommitDate(fiBacklogMesa);
|
||||
if (dateTime is not null)
|
||||
AddPatch(result, "/fields/Microsoft.VSTS.Scheduling.TargetDate", dateTime);
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.Updates))
|
||||
AddPatch(result, "/fields/System.History", fiBacklogMesa.Updates);
|
||||
AddPatch(result, "/fields/System.Title", title);
|
||||
if (requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
||||
AddPatch(result, "/fields/System.AssignedTo", requestorUser);
|
||||
// https://tfs.intra.infineon.com/tfs/ManufacturingIT/Mesa_FI/_apis/wit/workitemtypes/feature/fields?api-version=7.0
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<string> GetTags(FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
List<string> results = new();
|
||||
foreach (string tag in fiBacklogMesa.SystemS.Split('/'))
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.Trim()))
|
||||
continue;
|
||||
results.Add(tag.Trim());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static List<string> GetTags(Fields fields)
|
||||
{
|
||||
List<string> results = new();
|
||||
if (!string.IsNullOrEmpty(fields.SystemTags))
|
||||
{
|
||||
foreach (string tag in fields.SystemTags.Split(';'))
|
||||
{
|
||||
if (string.IsNullOrEmpty(tag.Trim()))
|
||||
continue;
|
||||
results.Add(tag.Trim());
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void DoWork(WorkItemTrackingHttpClient workItemTrackingHttpClient, string project, ReadOnlyDictionary<string, string> assignedToNameToUser, ReadOnlyDictionary<string, string> requestorNameToUser, FIBacklogMesa fiBacklogMesa)
|
||||
{
|
||||
DateTime dateTime;
|
||||
JsonPatchDocument tagDocument;
|
||||
List<string> tags = GetTags(fiBacklogMesa);
|
||||
Task<WorkItem>? secondResourceWorkItemTask = null;
|
||||
bool isBugFix = fiBacklogMesa.Priority == "0 - BugFix";
|
||||
if (!DateTime.TryParse(fiBacklogMesa.Submitted, out dateTime))
|
||||
dateTime = DateTime.MinValue;
|
||||
JsonPatchDocument uatDocument = GetUATDocument(project, requestorNameToUser, dateTime, fiBacklogMesa);
|
||||
Task<WorkItem> uatWorkItemTask = workItemTrackingHttpClient.CreateWorkItemAsync(uatDocument, project, "Task");
|
||||
uatWorkItemTask.Wait();
|
||||
if (isBugFix)
|
||||
{
|
||||
JsonPatchDocument bugDocument = GetBugDocument(project, assignedToNameToUser, uatWorkItemTask, fiBacklogMesa);
|
||||
Task<WorkItem> bugWorkItemTask = workItemTrackingHttpClient.CreateWorkItemAsync(bugDocument, project, "Bug");
|
||||
bugWorkItemTask.Wait();
|
||||
}
|
||||
if (!isBugFix)
|
||||
{
|
||||
JsonPatchDocument developerTaskDocument = GetDeveloperTaskDocument(project, assignedToNameToUser, fiBacklogMesa);
|
||||
Task<WorkItem> assignedToWorkItemTask = workItemTrackingHttpClient.CreateWorkItemAsync(developerTaskDocument, project, "Task");
|
||||
assignedToWorkItemTask.Wait();
|
||||
if (!string.IsNullOrEmpty(fiBacklogMesa.SecondResource))
|
||||
{
|
||||
JsonPatchDocument secondDeveloperTaskDocument = GetSecondDeveloperTaskDocument(project, assignedToNameToUser, fiBacklogMesa);
|
||||
secondResourceWorkItemTask = workItemTrackingHttpClient.CreateWorkItemAsync(secondDeveloperTaskDocument, project, "Task");
|
||||
secondResourceWorkItemTask.Wait();
|
||||
}
|
||||
JsonPatchDocument userStoryDocument = GetUserStoryDocument(project, requestorNameToUser, uatWorkItemTask, fiBacklogMesa);
|
||||
Task<WorkItem> userStoryWorkItemTask = workItemTrackingHttpClient.CreateWorkItemAsync(userStoryDocument, project, "User Story");
|
||||
userStoryWorkItemTask.Wait();
|
||||
if (userStoryWorkItemTask?.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
JsonPatchDocument assignedToRelationDocument = GetAssignedToRelationDocument(assignedToWorkItemTask);
|
||||
userStoryWorkItemTask = workItemTrackingHttpClient.UpdateWorkItemAsync(assignedToRelationDocument, userStoryWorkItemTask.Result.Id.Value);
|
||||
userStoryWorkItemTask.Wait();
|
||||
if (secondResourceWorkItemTask is not null)
|
||||
{
|
||||
if (userStoryWorkItemTask.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
JsonPatchDocument secondResourceDocument = GetSecondResourceDocument(secondResourceWorkItemTask);
|
||||
userStoryWorkItemTask = workItemTrackingHttpClient.UpdateWorkItemAsync(secondResourceDocument, userStoryWorkItemTask.Result.Id.Value);
|
||||
userStoryWorkItemTask.Wait();
|
||||
}
|
||||
JsonPatchDocument featureDocument = GetFeatureDocument(project, requestorNameToUser, tags, userStoryWorkItemTask, fiBacklogMesa);
|
||||
Task<WorkItem> featureWorkItemTask = workItemTrackingHttpClient.CreateWorkItemAsync(featureDocument, project, "Feature");
|
||||
featureWorkItemTask.Wait();
|
||||
for (int i = tags.Count - 1; i > -1; i--)
|
||||
{
|
||||
if (featureWorkItemTask.Result.Id is null)
|
||||
throw new NotSupportedException();
|
||||
tagDocument = new();
|
||||
AddPatch(tagDocument, "/fields/System.Tags", tags[i]);
|
||||
tags.RemoveAt(i);
|
||||
featureWorkItemTask = workItemTrackingHttpClient.UpdateWorkItemAsync(tagDocument, featureWorkItemTask.Result.Id.Value);
|
||||
featureWorkItemTask.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Parse(IFileRead fileRead,
|
||||
Logistics logistics,
|
||||
List<FileInfo> fileInfoCollection,
|
||||
HttpClient httpClient,
|
||||
string basePage,
|
||||
string api,
|
||||
string query,
|
||||
WorkItemTrackingHttpClient workItemTrackingHttpClient,
|
||||
string project,
|
||||
ReadOnlyDictionary<string, string> assignedToNameToEncodedPAT,
|
||||
ReadOnlyDictionary<string, string> assignedToNameToUser,
|
||||
ReadOnlyDictionary<string, string> requestorNameToUser,
|
||||
string json,
|
||||
bool forceUpdatedBy,
|
||||
bool forceDeleteUpdatedBy)
|
||||
{
|
||||
if (fileRead is null)
|
||||
throw new NullReferenceException();
|
||||
if (logistics is null)
|
||||
throw new NullReferenceException();
|
||||
if (fileInfoCollection is null)
|
||||
throw new NullReferenceException();
|
||||
int counter = 0;
|
||||
string forceUpdatedByComment = "Force updated by";
|
||||
string? directory = Path.GetDirectoryName(fileRead.ReportFullPath) ?? throw new Exception();
|
||||
string[] checkFiles = Directory.GetFiles(directory, "*.csv", SearchOption.TopDirectoryOnly);
|
||||
if (checkFiles.Length != 0)
|
||||
UpdateIds(httpClient, basePage, api, checkFiles);
|
||||
else
|
||||
{
|
||||
string ids = GetIds(httpClient, basePage, api, query);
|
||||
Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa = GetFIBacklogMesaCollection(json);
|
||||
Value[] workItems = string.IsNullOrEmpty(ids) ? Array.Empty<Value>() : GetWorkItems(fileRead, httpClient, basePage, api, ids);
|
||||
int count = keyToFIBacklogMesa.Count;
|
||||
ReadOnlyCollection<ValueWithReq> valueWithReqCollection = GetValueWithReqCollection(workItems);
|
||||
SetSyncTag(workItemTrackingHttpClient, requestorNameToUser, keyToFIBacklogMesa, valueWithReqCollection);
|
||||
ReadOnlyDictionary<string, List<int>> updateCollection = GetForceUpdatedByCollection(assignedToNameToEncodedPAT, assignedToNameToUser, keyToFIBacklogMesa, valueWithReqCollection);
|
||||
if (updateCollection.Count > 0 && forceUpdatedBy)
|
||||
ForceUpdatedBy(httpClient, basePage, project, api, forceUpdatedByComment, updateCollection);
|
||||
if (forceDeleteUpdatedBy)
|
||||
{
|
||||
ReadOnlyDictionary<string, List<int[]>> deleteCollection = GetForceUpdatedByCollectionDelete(forceUpdatedByComment, assignedToNameToEncodedPAT, assignedToNameToUser, keyToFIBacklogMesa, valueWithReqCollection);
|
||||
if (deleteCollection.Count > 0 && forceDeleteUpdatedBy)
|
||||
ForceUpdatedByDelete(httpClient, basePage, project, api, deleteCollection);
|
||||
}
|
||||
ReadOnlyCollection<ValueWithReq> extra = RemoveFrom(keyToFIBacklogMesa, valueWithReqCollection);
|
||||
if (count != extra.Count)
|
||||
{ }
|
||||
if (count != keyToFIBacklogMesa.Count)
|
||||
{ }
|
||||
_Details.AddRange(workItems);
|
||||
foreach (KeyValuePair<string, FIBacklogMesa> keyValuePair in keyToFIBacklogMesa)
|
||||
{
|
||||
if (counter > 5)
|
||||
break;
|
||||
if (!fileRead.IsEAFHosted)
|
||||
continue;
|
||||
DoWork(workItemTrackingHttpClient, project, assignedToNameToUser, requestorNameToUser, keyValuePair.Value);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Parse() =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
}
|
Reference in New Issue
Block a user