Skip to content

Commit

Permalink
Update - lots of fin with async!
Browse files Browse the repository at this point in the history
  • Loading branch information
MrHinsh committed Jun 28, 2024
1 parent 2686719 commit 7b60d74
Show file tree
Hide file tree
Showing 14 changed files with 4,171 additions and 117 deletions.
2 changes: 1 addition & 1 deletion ABB.WorkItemClone.AzureDevOps/Authenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public async Task<string> AuthenticationCommand(string? token)
string auth = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token)));
return $"Basic {auth}";
}

throw new ArgumentNullException("Token is null");
try
{
var authResult = await SignInUserAndGetTokenUsingMSAL(scopes);
Expand Down
31 changes: 29 additions & 2 deletions ABB.WorkItemClone.AzureDevOps/AzureDevOpsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace ABB.WorkItemClone.AzureDevOps
{
public class AzureDevOpsApi
public class AzureDevOpsApi : IAsyncDisposable
{
private readonly string _authHeader;
private readonly string _account;
Expand All @@ -22,6 +22,30 @@ public AzureDevOpsApi(string token, string account, string project)
_project = project;
}

public Task<List<WorkItemFull>> GetWorkItemsFullAsync()
{
var fakeItems = GetWiqlQueryResults().Result;

List<WorkItemFull> realItems = new List<WorkItemFull>();
foreach (var item in fakeItems.workItems)
{
realItems.Add(GetWorkItem((int)item.id).Result);
}
return Task.FromResult(realItems);
}

public async IAsyncEnumerable<WorkItemFull> GetWorkItemsFullAsync(Workitem[] itemsToGet)
{
for (var i = 0; i < itemsToGet.Length; ++i)
{
//await Task.Delay(TimeSpan.FromMilliseconds(1000));
WorkItemFull result = await GetWorkItem((int)itemsToGet[i].id);
//WorkItemFull result = new WorkItemFull();
yield return result;
}
}


public async Task<QueryResults?> GetWiqlQueryResults()
{
string post = JsonConvert.SerializeObject(new {
Expand Down Expand Up @@ -113,6 +137,9 @@ private async Task<string> GetResult(string apiToCall, string? post, string? med
return default(T);
}


public ValueTask DisposeAsync()
{
return new(Task.Delay(TimeSpan.FromSeconds(1)));
}
}
}
2 changes: 1 addition & 1 deletion ABB.WorkItemClone.AzureDevOps/DataContracts/WorkItemAdd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class WorkItemAdd
{
public List<Operation> Operations { get; set; } = new List<Operation>();
public WorkItemFull? ItemFromtemplate { get; set; }
public MergeWorkItem ItemFromConfig { get; set; }
public jsonWorkItem ItemFromConfig { get; set; }
}

public abstract class Operation
Expand Down
13 changes: 13 additions & 0 deletions ABB.WorkItemClone.AzureDevOps/DataContracts/WorkItemToBuild.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@


namespace ABB.WorkItemClone.AzureDevOps.DataContracts
{
public class WorkItemToBuild
{
public Guid guid { get; set; }
public int? templateId { get; set; }
public Dictionary<string, string> fields { get; set; }
public List<WorkItemToBuildRelation> relations { get; set; }

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

namespace ABB.WorkItemClone.AzureDevOps.DataContracts
{
public class WorkItemToBuildRelation
{
public WorkItemToBuildRelation()
{
}

public string rel { get; set; }
public Guid guid { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
namespace ABB.WorkItemClone.AzureDevOps.DataContracts
{

public class MergeWorkItem
public class jsonWorkItem
{
public int? id { get; set; }
public string? area { get; set; }
public string? tags { get; set; }
public MergeFields? fields { get; set; }
public jsonFields? fields { get; set; }
}

public class MergeFields
public class jsonFields
{
public string? title { get; set; }
public string? product { get; set; }
Expand Down
8 changes: 4 additions & 4 deletions ABB.WorkItemClone.ConsoleUI/Commands/WorkItemCloneCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

namespace ABB.WorkItemClone.ConsoleUI.Commands
{
internal class WorkItemCloneCommand : Command<WorkItemCloneCommandSettings>
internal class WorkItemCloneCommand : WorkItemCommandBase<WorkItemCloneCommandSettings>
{
public override int Execute(CommandContext context, WorkItemCloneCommandSettings settings)
public override async Task<int> ExecuteAsync(CommandContext context, WorkItemCloneCommandSettings settings)
{
AnsiConsole.Write(new Rule("Clone Work Items").LeftJustified());

Expand All @@ -28,10 +28,10 @@ public override int Execute(CommandContext context, WorkItemCloneCommandSettings
ConfigurationSettings configSettings = JsonConvert.DeserializeObject<ConfigurationSettings>(System.IO.File.ReadAllText(settings.configFile));


List<MergeWorkItem> configWorkItems;
List<jsonWorkItem> configWorkItems;
try
{
configWorkItems = JsonConvert.DeserializeObject<List<MergeWorkItem>>(File.ReadAllText(settings.JsonFile));
configWorkItems = JsonConvert.DeserializeObject<List<jsonWorkItem>>(File.ReadAllText(settings.JsonFile));
}
catch (Exception ex)
{
Expand Down
177 changes: 177 additions & 0 deletions ABB.WorkItemClone.ConsoleUI/Commands/WorkItemCommandBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
using ABB.WorkItemClone.AzureDevOps;
using ABB.WorkItemClone.AzureDevOps.DataContracts;
using ABB.WorkItemClone.ConsoleUI.DataContracts;
using Newtonsoft.Json;
using Spectre.Console;
using Spectre.Console.Cli;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ABB.WorkItemClone.ConsoleUI.Commands
{
internal abstract class WorkItemCommandBase<TSettings> : AsyncCommand<TSettings> where TSettings : CommandSettings
{

internal int EnsureProjectIdAskIfMissing(int? projectId)
{
if (projectId == null)
{
projectId = AnsiConsole.Prompt(
new TextPrompt<int>("What is the project Id?")
.Validate(projectId
=> projectId > 0
? ValidationResult.Success()
: ValidationResult.Error("[yellow]Invalid project Id[/]")));
}
return projectId.Value;
}

internal List<jsonWorkItem> LoadJsonFile(string? jsonFile)
{
jsonFile = EnsureJsonFileAskIfMissing(jsonFile);
if (!System.IO.File.Exists(jsonFile))
{
AnsiConsole.MarkupLine("[red]Error:[/] No JSON file was found.");
throw new Exception(jsonFile + " not found.");
}
List<jsonWorkItem> configWorkItems;
try
{
configWorkItems = JsonConvert.DeserializeObject<List<jsonWorkItem>>(File.ReadAllText(jsonFile));
}
catch (Exception ex)
{
AnsiConsole.MarkupLine("[red]Error:[/] No JSON file was malformed.");
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
throw new Exception(jsonFile + " is malformed.");
}
if (configWorkItems?.Count == 0)
{
AnsiConsole.MarkupLine("[red]Error:[/] No JSON file is empty.");
throw new Exception(jsonFile + " is empty.");
}
return configWorkItems;
}

internal string EnsureJsonFileAskIfMissing(string? jsonFile)
{
if (jsonFile == null)
{
jsonFile = AnsiConsole.Prompt(
new TextPrompt<string>("Where is the JSON File?")
.Validate(jsonFile
=> !string.IsNullOrWhiteSpace(jsonFile)
? ValidationResult.Success()
: ValidationResult.Error("[yellow]Invalid JSON file[/]")));
}
return jsonFile;
}

internal DirectoryInfo CreateOutputPath(string? outputPath)
{
outputPath = EnsureOutputPathAskIfMissing(outputPath);
if (!System.IO.Directory.Exists(outputPath))
{
System.IO.Directory.CreateDirectory(outputPath);
}
return new DirectoryInfo(outputPath);
}

internal string EnsureOutputPathAskIfMissing(string? outputPath)
{
if (outputPath == null)
{
outputPath = AnsiConsole.Prompt(
new TextPrompt<string>("What is the output path?")
.Validate(outputPath
=> !string.IsNullOrWhiteSpace(outputPath)
? ValidationResult.Success()
: ValidationResult.Error("[yellow]Invalid output path[/]")));
}
return outputPath;
}

internal AzureDevOpsApi CreateAzureDevOpsConnection(string? accessToken, string? organization, string? project)
{
organization = EnsureOrganizationAskIfMissing(organization);
project = EnsureProjectAskIfMissing(project);
accessToken = EnsureAccessTokenAskIfMissing(accessToken, organization);
return new AzureDevOpsApi(accessToken, organization, project);
}

private string EnsureProjectAskIfMissing(string? project)
{
if (project == null)
{

project = AnsiConsole.Prompt(
new TextPrompt<string>("What is the project?")
.Validate(project
=> !string.IsNullOrWhiteSpace(project)
? ValidationResult.Success()
: ValidationResult.Error("[yellow]Invalid project[/]")));
}
return project;
}

private string EnsureOrganizationAskIfMissing(string? organization)
{
if (organization == null)
{

organization = AnsiConsole.Prompt(
new TextPrompt<string>("What is the organization?")
.Validate(organization
=> !string.IsNullOrWhiteSpace(organization)
? ValidationResult.Success()
: ValidationResult.Error("[yellow]Invalid organization[/]")));
}
return organization;
}

private string EnsureAccessTokenAskIfMissing(string? accessToken, string organization)
{
if (accessToken == null)
{

accessToken = AnsiConsole.Prompt(
new TextPrompt<string>($"Provide a valid Access Token for {organization}?")
.Validate(accessToken
=> !string.IsNullOrWhiteSpace(accessToken)
? ValidationResult.Success()
: ValidationResult.Error("[yellow]Invalid access token[/]")));
}
return accessToken;
}

internal ConfigurationSettings LoadConfigFile(string? configFile)
{
ConfigurationSettings configSettings = System.Text.Json.JsonSerializer.Deserialize<ConfigurationSettings>(System.IO.File.ReadAllText(configFile));
return configSettings;
}

internal string EnsureConfigFileAskIfMissing(string? configFile)
{
if (configFile == null)
{

configFile = AnsiConsole.Prompt(
new TextPrompt<string>("Where is the config File?")
.Validate(configFile
=> !string.IsNullOrWhiteSpace(configFile)
? ValidationResult.Success()
: ValidationResult.Error("[yellow]Invalid config file[/]")));
}
if (!System.IO.File.Exists(configFile))
{
AnsiConsole.MarkupLine("[red]Error:[/] No JSON file was found.");
throw new Exception(configFile + " not found.");
}
return configFile;
}

}
}
Loading

0 comments on commit 7b60d74

Please sign in to comment.