560 lines
27 KiB
C#
560 lines
27 KiB
C#
using File_Folder_Helper.Day.Q32024.ConvertExcelToJson;
|
|
using File_Folder_Helper.Day.Q32024.WorkItems;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
|
|
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
|
|
using Microsoft.VisualStudio.Services.Common;
|
|
using Microsoft.VisualStudio.Services.WebApi;
|
|
using Microsoft.VisualStudio.Services.WebApi.Patch;
|
|
using Microsoft.VisualStudio.Services.WebApi.Patch.Json;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Net.Http.Headers;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Web;
|
|
|
|
namespace File_Folder_Helper.Day.Q32024;
|
|
|
|
internal static partial class Helper20240809
|
|
{
|
|
|
|
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 = [];
|
|
string key;
|
|
FIBacklogMesa[]? fiBacklogMesaCollection;
|
|
fiBacklogMesaCollection = JsonSerializer.Deserialize(json, FIBacklogMesaCollectionSourceGenerationContext.Default.FIBacklogMesaArray);
|
|
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(streamTask.Result, WIQL.WIQLRootSourceGenerationContext.Default.Root);
|
|
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 ReadOnlyCollection<ValueWithReq> GetWorkItems(HttpClient httpClient, string sourceDirectory, string basePage, string api, string ids)
|
|
{
|
|
List<ValueWithReq> results = [];
|
|
int req;
|
|
string json;
|
|
string file;
|
|
Value? value;
|
|
string[] segments;
|
|
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? result = JsonSerializer.Deserialize<JsonElement>(streamTask.Result);
|
|
if (result is null || result.Value.ValueKind != JsonValueKind.Object)
|
|
throw new NullReferenceException(nameof(result));
|
|
JsonElement[] jsonElements = result.Value.EnumerateObject().Last().Value.EnumerateArray().ToArray();
|
|
foreach (JsonElement jsonElement in jsonElements)
|
|
{
|
|
json = jsonElement.GetRawText();
|
|
value = JsonSerializer.Deserialize(json, ValueSourceGenerationContext.Default.Value);
|
|
if (value is null)
|
|
continue;
|
|
segments = value.Fields.SystemTitle.Split('-');
|
|
if (segments.Length < 2)
|
|
continue;
|
|
if (!int.TryParse(segments[0], out req) || req == 0)
|
|
continue;
|
|
file = Path.Combine(sourceDirectory, $"{req}.json");
|
|
File.WriteAllText(file, json);
|
|
results.Add(new(value, req, json));
|
|
}
|
|
return new(results);
|
|
}
|
|
|
|
private static ReadOnlyCollection<ValueWithReq> RemoveFrom(Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa, ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
|
{
|
|
List<ValueWithReq> results = [];
|
|
foreach (ValueWithReq valueWithReq in valueWithReqCollection)
|
|
{
|
|
if (keyToFIBacklogMesa.Remove($"{valueWithReq.Req} - "))
|
|
continue;
|
|
results.Add(valueWithReq);
|
|
}
|
|
return new(results);
|
|
}
|
|
|
|
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 (string.IsNullOrEmpty(fiBacklogMesa.Priority) || !int.TryParse(fiBacklogMesa.Priority[..1], out int priority) || priority == 0 || priority > 3)
|
|
result = 4;
|
|
else
|
|
result = priority;
|
|
return result;
|
|
}
|
|
|
|
private static int? GetPrioritySubset(FIBacklogMesa fiBacklogMesa)
|
|
{
|
|
int? result;
|
|
if (string.IsNullOrEmpty(fiBacklogMesa.PrioritySubset) || !int.TryParse(fiBacklogMesa.PrioritySubset[..1], out int prioritySubset) || prioritySubset == 0 || prioritySubset > 3)
|
|
result = null;
|
|
else
|
|
result = prioritySubset;
|
|
return result;
|
|
}
|
|
|
|
private static string GetIterationPath(string project, DateTime submittedDateTime) =>
|
|
submittedDateTime.Year != 2024 ? project : string.Concat(project, "\\", submittedDateTime.Year);
|
|
|
|
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[..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[..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 JsonPatchDocument GetBugDocument(string project, string site, ReadOnlyDictionary<string, string> assignedToNameToUser, ReadOnlyDictionary<string, string> requestorNameToUser, Task<WorkItem>? uatWorkItemTask, FIBacklogMesa fiBacklogMesa, DateTime submittedDateTime)
|
|
{
|
|
JsonPatchDocument result = [];
|
|
string title = GetTitle(fiBacklogMesa);
|
|
string iterationPath = GetIterationPath(project, submittedDateTime);
|
|
if (uatWorkItemTask?.Result.Id is not null)
|
|
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = uatWorkItemTask.Result.Url });
|
|
AddPatch(result, "/fields/System.AreaPath", string.Concat(project, "\\", site));
|
|
AddPatch(result, "/fields/System.IterationPath", iterationPath);
|
|
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.Subject}<br> <br>{fiBacklogMesa.Definition}");
|
|
if (assignedToNameToUser.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToUser))
|
|
AddPatch(result, "/fields/System.AssignedTo", assignedToUser);
|
|
if (requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
|
AddPatch(result, "/fields/Custom.Requester", requestorUser);
|
|
return result;
|
|
}
|
|
|
|
private static JsonPatchDocument GetFeatureDocument(string project, string site, ReadOnlyDictionary<string, string> requestorNameToUser, ReadOnlyDictionary<string, string> assignedToNameToUser, List<string> tags, Task<WorkItem>? userStoryWorkItemTask, FIBacklogMesa fiBacklogMesa, DateTime submittedDateTime)
|
|
{
|
|
JsonPatchDocument result = [];
|
|
string title = GetTitle(fiBacklogMesa);
|
|
int priority = GetPriority(fiBacklogMesa);
|
|
string? state = GetMappedState(fiBacklogMesa);
|
|
int? prioritySubset = GetPrioritySubset(fiBacklogMesa);
|
|
if (prioritySubset is not null)
|
|
AddPatch(result, "/fields/Microsoft.VSTS.Common.TimeCriticality", prioritySubset);
|
|
string iterationPath = GetIterationPath(project, submittedDateTime);
|
|
if (userStoryWorkItemTask?.Result.Id is not null)
|
|
AddPatch(result, "/relations/-", new WorkItemRelation() { Rel = "System.LinkTypes.Hierarchy-Forward", Url = userStoryWorkItemTask.Result.Url });
|
|
AddPatch(result, "/fields/System.AreaPath", string.Concat(project, "\\", site));
|
|
if (tags.Count > 0)
|
|
{
|
|
AddPatch(result, "/fields/System.Tags", tags.Last());
|
|
tags.RemoveAt(tags.Count - 1);
|
|
}
|
|
AddPatch(result, "/fields/System.IterationPath", iterationPath);
|
|
AddPatch(result, "/fields/Microsoft.VSTS.Common.Priority", priority);
|
|
if (!string.IsNullOrEmpty(fiBacklogMesa.Definition))
|
|
AddPatch(result, "/fields/System.Description", $"{fiBacklogMesa.Subject}<br> <br>{fiBacklogMesa.Definition}");
|
|
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 (assignedToNameToUser.TryGetValue(fiBacklogMesa.AssignedTo, out string? assignedToUser))
|
|
AddPatch(result, "/fields/System.AssignedTo", assignedToUser);
|
|
if (requestorNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? requestorUser))
|
|
AddPatch(result, "/fields/Custom.Requester", 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 = [];
|
|
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 = [];
|
|
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 CreateWorkItem(WorkItemTrackingHttpClient workItemTrackingHttpClient, string project, string site, ReadOnlyDictionary<string, string> assignedToNameToUser, ReadOnlyDictionary<string, string> requestorNameToUser, FIBacklogMesa fiBacklogMesa)
|
|
{
|
|
DateTime submittedDateTime;
|
|
JsonPatchDocument tagDocument;
|
|
Task<WorkItem>? workItem = null;
|
|
List<string> tags = GetTags(fiBacklogMesa);
|
|
bool isBugFix = fiBacklogMesa.Priority == "0 - BugFix";
|
|
if (assignedToNameToUser.Count > requestorNameToUser.Count)
|
|
throw new Exception();
|
|
if (!DateTime.TryParse(fiBacklogMesa.Submitted, out submittedDateTime))
|
|
submittedDateTime = DateTime.MinValue;
|
|
if (isBugFix)
|
|
{
|
|
Task<WorkItem>? uatWorkItemTask = null;
|
|
JsonPatchDocument bugDocument = GetBugDocument(project, site, requestorNameToUser, assignedToNameToUser, uatWorkItemTask, fiBacklogMesa, submittedDateTime);
|
|
workItem = workItemTrackingHttpClient.CreateWorkItemAsync(bugDocument, project, "Bug");
|
|
workItem.Wait();
|
|
}
|
|
if (!isBugFix)
|
|
{
|
|
Task<WorkItem>? userStoryWorkItemTask = null;
|
|
JsonPatchDocument featureDocument = GetFeatureDocument(project, site, requestorNameToUser, assignedToNameToUser, tags, userStoryWorkItemTask, fiBacklogMesa, submittedDateTime);
|
|
workItem = workItemTrackingHttpClient.CreateWorkItemAsync(featureDocument, project, "Feature");
|
|
workItem.Wait();
|
|
}
|
|
for (int i = tags.Count - 1; i > -1; i--)
|
|
{
|
|
if (workItem is null)
|
|
continue;
|
|
if (workItem.Result.Id is null)
|
|
throw new NotSupportedException();
|
|
tagDocument = [];
|
|
AddPatch(tagDocument, "/fields/System.Tags", tags[i]);
|
|
tags.RemoveAt(i);
|
|
workItem = workItemTrackingHttpClient.UpdateWorkItemAsync(tagDocument, workItem.Result.Id.Value);
|
|
workItem.Wait();
|
|
}
|
|
}
|
|
|
|
private static void KillTime(int loops)
|
|
{
|
|
for (int i = 1; i < loops; i++)
|
|
Thread.Sleep(500);
|
|
}
|
|
|
|
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 Update(HttpClient httpClient, string basePage, string api, WorkItemTrackingHttpClient workItemTrackingHttpClient, string sync, ValueWithReq valueWithReq)
|
|
{
|
|
JsonPatchDocument result = [];
|
|
AddPatch(result, "/fields/System.Tags", sync);
|
|
Task<WorkItem> workItem = workItemTrackingHttpClient.UpdateWorkItemAsync(result, valueWithReq.Value.Id);
|
|
workItem.Wait();
|
|
if (result is null)
|
|
{
|
|
var payload = new
|
|
{
|
|
op = "replace",
|
|
path = "/fields/System.IterationPath",
|
|
value = "Mesa_FI"
|
|
};
|
|
string stringPayload = JsonSerializer.Serialize(payload);
|
|
HttpContent httpContent = new StringContent($"[{stringPayload}]", Encoding.UTF8, "application/json-patch+json");
|
|
Update(httpClient, basePage, api, $"/workitems/{valueWithReq.Value.Id}?api-version=1.0", httpContent);
|
|
}
|
|
}
|
|
|
|
private static int SetSyncTag(HttpClient httpClient,
|
|
string basePage,
|
|
string api,
|
|
WorkItemTrackingHttpClient workItemTrackingHttpClient,
|
|
ReadOnlyDictionary<string, string> assignedToNameToUser,
|
|
ReadOnlyDictionary<string, string> requestorNameToUser,
|
|
Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa,
|
|
ReadOnlyCollection<ValueWithReq> valueWithReqCollection)
|
|
{
|
|
int result = 0;
|
|
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.CustomRequester is null || !valueWithReq.Value.Fields.CustomRequester.UniqueName.Equals(requestorUser, StringComparison.CurrentCultureIgnoreCase)))
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
_ = assignedToNameToUser.TryGetValue(fiBacklogMesa.Requestor, out string? assignedToUser);
|
|
if (!string.IsNullOrEmpty(assignedToUser) && (valueWithReq.Value.Fields.SystemAssignedTo is null || !valueWithReq.Value.Fields.SystemAssignedTo.UniqueName.Equals(assignedToUser, StringComparison.CurrentCultureIgnoreCase)))
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
if (valueWithReq.Value.Fields.SystemTitle != title)
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
foreach (string tag in tags)
|
|
{
|
|
if (compareTags.Contains(tag))
|
|
continue;
|
|
_ = tags.Remove(tag);
|
|
break;
|
|
}
|
|
if (tags.Count != compareTags.Count)
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
if ((isBugFix && valueWithReq.Value.Fields.SystemWorkItemType != "Bug") || (!isBugFix && valueWithReq.Value.Fields.SystemWorkItemType == "Bug"))
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
if (!isBugFix)
|
|
{
|
|
priority = GetPriority(fiBacklogMesa);
|
|
if (valueWithReq.Value.Fields.MicrosoftVSTSCommonPriority != priority)
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
}
|
|
state = GetMappedState(fiBacklogMesa);
|
|
if (!string.IsNullOrEmpty(state) && valueWithReq.Value.Fields.SystemState != state)
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
if (!isBugFix && int.TryParse(fiBacklogMesa.EstEffortDays, out int estEffortDays) && valueWithReq.Value.Fields.Effort != estEffortDays)
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, 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)
|
|
{
|
|
result += 1;
|
|
Update(httpClient, basePage, api, workItemTrackingHttpClient, sync, valueWithReq);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static void CreateWorkItems(HttpClient httpClient,
|
|
string sourceDirectory,
|
|
string basePage,
|
|
string api,
|
|
string query,
|
|
WorkItemTrackingHttpClient workItemTrackingHttpClient,
|
|
string project,
|
|
string site,
|
|
ReadOnlyDictionary<string, string> assignedToNameToUser,
|
|
ReadOnlyDictionary<string, string> requestorNameToUser,
|
|
string json)
|
|
{
|
|
int counter = 0;
|
|
string ids = GetIds(httpClient, basePage, api, query);
|
|
Dictionary<string, FIBacklogMesa> keyToFIBacklogMesa = GetFIBacklogMesaCollection(json);
|
|
ReadOnlyCollection<ValueWithReq> valueWithReqCollection = string.IsNullOrEmpty(ids) ? new([]) : GetWorkItems(httpClient, sourceDirectory, basePage, api, ids);
|
|
int updated = SetSyncTag(httpClient, basePage, api, workItemTrackingHttpClient, assignedToNameToUser, requestorNameToUser, keyToFIBacklogMesa, valueWithReqCollection);
|
|
if (updated == 0)
|
|
{
|
|
ReadOnlyCollection<ValueWithReq> extra = RemoveFrom(keyToFIBacklogMesa, valueWithReqCollection);
|
|
foreach (KeyValuePair<string, FIBacklogMesa> keyValuePair in keyToFIBacklogMesa)
|
|
{
|
|
if (keyToFIBacklogMesa.Count == extra.Count)
|
|
break;
|
|
CreateWorkItem(workItemTrackingHttpClient, project, site, assignedToNameToUser, requestorNameToUser, keyValuePair.Value);
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private static void CreateWorkItems(ILogger<Worker> logger, string sourceDirectory, string api, string site, string query, string project, string basePage, string baseAddress, byte[] bytes, string[] assignedToNames, string[] requestorNames, string reportFullPath, MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeaderValue, WorkItemTrackingHttpClient workItemTrackingHttpClient, HttpClient httpClient)
|
|
{
|
|
string base64 = Convert.ToBase64String(bytes);
|
|
string json = File.ReadAllText(reportFullPath);
|
|
httpClient.DefaultRequestHeaders.Authorization = new("Basic", base64);
|
|
httpClient.DefaultRequestHeaders.Accept.Add(mediaTypeWithQualityHeaderValue);
|
|
ReadOnlyDictionary<string, string> requestorNameToUser = GetRequestorNameToUser(requestorNames);
|
|
ReadOnlyDictionary<string, string> assignedToNameToUser = GetAssignedToNameToUser(assignedToNames);
|
|
logger.LogInformation("{baseAddress}{basePage}/{project}{api}{query}", baseAddress, basePage, HttpUtility.HtmlEncode(project), api, query);
|
|
CreateWorkItems(httpClient, sourceDirectory, basePage, api, query, workItemTrackingHttpClient, project, site, new(assignedToNameToUser), new(requestorNameToUser), json);
|
|
}
|
|
|
|
private static ReadOnlyDictionary<string, string> GetAssignedToNameToUser(string[] assignedToNames)
|
|
{
|
|
Dictionary<string, string> results = [];
|
|
string[] segments;
|
|
foreach (string assignedToName in assignedToNames)
|
|
{
|
|
segments = assignedToName.Split('|');
|
|
if (segments.Length != 2)
|
|
continue;
|
|
results.Add(segments[0], segments[1]);
|
|
}
|
|
return new(results);
|
|
}
|
|
|
|
private static ReadOnlyDictionary<string, string> GetRequestorNameToUser(string[] requestorNames)
|
|
{
|
|
Dictionary<string, string> results = [];
|
|
string[] segments;
|
|
foreach (string requestorName in requestorNames)
|
|
{
|
|
segments = requestorName.Split('|');
|
|
if (segments.Length != 2)
|
|
continue;
|
|
results.Add(segments[0], segments[1]);
|
|
}
|
|
return new(results);
|
|
}
|
|
|
|
internal static void CreateWorkItems(ILogger<Worker> logger, List<string> args)
|
|
{
|
|
string api = args[6];
|
|
string pat = args[8];
|
|
string site = args[2];
|
|
string query = args[7];
|
|
string project = args[5];
|
|
string basePage = args[4];
|
|
string baseAddress = args[3];
|
|
string sourceDirectory = args[0];
|
|
VssBasicCredential credential = new("", pat);
|
|
string[] requestorNames = args[11].Split(',');
|
|
string[] assignedToNames = args[10].Split(',');
|
|
byte[] bytes = Encoding.ASCII.GetBytes($":{pat}");
|
|
string reportFullPath = Path.GetFullPath(Path.Combine(sourceDirectory, args[9]));
|
|
VssConnection connection = new(new(string.Concat(baseAddress, basePage)), credential);
|
|
MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeaderValue = new("application/json");
|
|
WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient<WorkItemTrackingHttpClient>();
|
|
HttpClient httpClient = new(new HttpClientHandler() { UseDefaultCredentials = true }) { BaseAddress = new(baseAddress) };
|
|
CreateWorkItems(logger, sourceDirectory, api, site, query, project, basePage, baseAddress, bytes, assignedToNames, requestorNames, reportFullPath, mediaTypeWithQualityHeaderValue, workItemTrackingHttpClient, httpClient);
|
|
}
|
|
|
|
} |