diff --git a/MSStore.API/MSStore.API.csproj b/MSStore.API/MSStore.API.csproj
index 979416e..d49d4b7 100644
--- a/MSStore.API/MSStore.API.csproj
+++ b/MSStore.API/MSStore.API.csproj
@@ -21,9 +21,9 @@
-
-
-
+
+
+
diff --git a/MSStore.CLI.UnitTests/BaseCommandLineTest.cs b/MSStore.CLI.UnitTests/BaseCommandLineTest.cs
index b845360..06f7194 100644
--- a/MSStore.CLI.UnitTests/BaseCommandLineTest.cs
+++ b/MSStore.CLI.UnitTests/BaseCommandLineTest.cs
@@ -2,11 +2,7 @@
// Licensed under the MIT License.
using System.CommandLine;
-using System.CommandLine.Builder;
-using System.CommandLine.Hosting;
using System.CommandLine.Invocation;
-using System.CommandLine.IO;
-using System.CommandLine.Parsing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
@@ -35,7 +31,6 @@ namespace MSStore.CLI.UnitTests
{
public class BaseCommandLineTest
{
- internal MicrosoftStoreCLI Cli { get; private set; } = null!;
internal Mock FakeConsole { get; private set; } = null!;
internal Mock> FakeConfigurationManager { get; private set; } = null!;
internal Mock> FakeTelemetryConfigurationManager { get; private set; } = null!;
@@ -97,7 +92,7 @@ public class BaseCommandLineTest
Id = new Guid("F3C1CCB6-09C0-4BAB-BABA-C034BFB60EF9")
};
- private Parser _parser = null!;
+ private IHostBuilder _hostBuilder = null!;
protected IAnsiConsole ErrorAnsiConsole { get; private set; } = null!;
protected static string CopyFilesRecursively(string sourcePath, [CallerMemberName] string caller = null!)
@@ -204,12 +199,8 @@ public void Initialize()
.Setup(fac => fac.CreatePackagedAsync(It.IsAny(), It.IsAny()))
.ReturnsAsync(FakeStorePackagedAPI.Object);
- Cli = [];
-
StorePackagedAPI.DefaultSubmissionPollDelay = TimeSpan.Zero;
- Cli.AddCommand(new TestCommand(this));
-
var azureBlobManagerMock = new Mock();
azureBlobManagerMock
.Setup(x => x.UploadFileAsync(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()))
@@ -242,8 +233,7 @@ public void Initialize()
TokenManager = new Mock();
- var builder = new CommandLineBuilder(Cli);
- _parser = builder.UseHost(_ => Host.CreateDefaultBuilder(null), (builder) => builder
+ _hostBuilder = Host.CreateDefaultBuilder(null)
.UseEnvironment("CLI")
.ConfigureServices((hostContext, services) =>
{
@@ -279,8 +269,7 @@ public void Initialize()
.AddScoped(sp => PWAAppInfoManager.Object)
.AddScoped(sp => ElectronManifestManager.Object)
.AddScoped(sp => NuGetPackageManager.Object)
- .AddScoped(sp => AppXManifestManager.Object)
- .AddSingleton(Cli);
+ .AddScoped(sp => AppXManifestManager.Object);
services.AddLogging(builder =>
{
@@ -292,39 +281,7 @@ public void Initialize()
.ConfigureLogging((hostContext, logging) =>
{
logging.SetMinimumLevel(LogLevel.Debug);
- }))
- .AddMiddleware(
- async (context, next) =>
- {
- var ct = context.GetCancellationToken();
-
- var host = context.GetHost();
-
- var configurationManager = host.Services.GetService>()!;
- var credentialManager = host.Services.GetService()!;
- var consoleReader = host.Services.GetService()!;
- var cliConfigurator = host.Services.GetService()!;
- var logger = host.Services.GetService>()!;
-
- if (context.ParseResult.CommandResult.Command is MicrosoftStoreCLI
- || context.ParseResult.CommandResult.Command is ReconfigureCommand
- || context.ParseResult.CommandResult.Command is TestCommand
- || await MicrosoftStoreCLI.InitAsync(ErrorAnsiConsole, configurationManager, credentialManager, consoleReader, cliConfigurator, logger, ct))
- {
- await next(context).ConfigureAwait(false);
- }
- }, MiddlewareOrder.Default)
- .UseVersionOption()
- .UseEnvironmentVariableDirective()
- .UseParseDirective()
- .UseSuggestDirective()
- .RegisterWithDotnetSuggest()
- .UseTypoCorrections()
- .UseParseErrorReporting()
- .UseExceptionHandler()
- .UseHelp()
- .CancelOnProcessTermination()
- .Build();
+ });
}
protected void FakeLogin(string? publisherDisplayName = null)
@@ -792,7 +749,7 @@ protected void SetupBasedOnTestDataProjectSubPath(DirectoryInfo dirInfo, string[
}
}
- protected Task<(string Output, string Error)> RunTestAsync(Func? testCallback)
+ protected Task<(string Output, string Error)> RunTestAsync(Func? testCallback)
{
_testCallback = testCallback;
@@ -818,19 +775,39 @@ protected void SetupBasedOnTestDataProjectSubPath(DirectoryInfo dirInfo, string[
AnsiConsole.Profile.Capabilities.Ansi = true;
AnsiConsole.Profile.Capabilities.Unicode = true;
- var parseResult = _parser.Parse(args);
+ IHost host = _hostBuilder.Start();
- if (parseResult.Errors.Any())
+ var storeCLI = host.Services.GetRequiredService();
+ storeCLI.Subcommands.Add(new TestCommand(this, host));
+ var parseResult = storeCLI.Parse(args);
+
+ IHostApplicationLifetime lifetime = host.Services.GetRequiredService();
+
+ if (parseResult.CommandResult.Command is not MicrosoftStoreCLI
+ && parseResult.CommandResult.Command is not ReconfigureCommand
+ && parseResult.CommandResult.Command is not TestCommand
+ && !await MicrosoftStoreCLI.InitAsync(ErrorAnsiConsole, host.Services.GetService>()!, host.Services.GetService()!, host.Services.GetService()!, host.Services.GetService()!, host.Services.GetService>()!, lifetime.ApplicationStopping))
+ {
+ // Initialization failed
+ await host.StopAsync();
+ return (Output: string.Empty, Error: string.Empty);
+ }
+
+ if (parseResult.Action is ParseErrorAction parseError)
{
- throw new ArgumentException(string.Join(Environment.NewLine, parseResult.Errors.Select(e => e.Message)));
+ parseError.ShowTypoCorrections = true;
+ parseError.ShowHelp = true;
}
- var testOutputConsole = new TestConsole(outputCapture, errorCapture);
+ parseResult.InvocationConfiguration.Output = outputCapture;
+ parseResult.InvocationConfiguration.Error = errorCapture;
- var invokeTask = parseResult.InvokeAsync(testOutputConsole);
+ var invokeTask = parseResult.InvokeAsync(parseResult.InvocationConfiguration);
var result = await invokeTask.ConfigureAwait(false);
+ await host.StopAsync();
+
if (expectedResult.HasValue)
{
result.Should().Be(expectedResult.Value);
@@ -858,13 +835,13 @@ private OutputCapture RefreshAnsiConsole()
return errorCapture;
}
- private Func? _testCallback;
+ private Func? _testCallback;
- private async Task TestAsync(InvocationContext invocationContext)
+ private async Task TestAsync(ParseResult parseResult, IHost host, CancellationToken cancellationToken)
{
if (_testCallback != null)
{
- await _testCallback(invocationContext);
+ await _testCallback(parseResult, host, cancellationToken);
}
}
@@ -872,15 +849,15 @@ private sealed class TestCommand : Command
{
private readonly BaseCommandLineTest _baseCommandLineTest;
- public TestCommand(BaseCommandLineTest baseCommandLineTest)
+ public TestCommand(BaseCommandLineTest baseCommandLineTest, IHost host)
: base("test")
{
_baseCommandLineTest = baseCommandLineTest;
- this.SetHandler(_baseCommandLineTest.TestAsync);
+ SetAction((parseResult, ct) => _baseCommandLineTest.TestAsync(parseResult, host, ct));
}
}
- internal sealed class OutputCapture : TextWriter, IStandardStreamWriter, IDisposable
+ internal sealed class OutputCapture : TextWriter, IDisposable
{
#pragma warning disable CA2213 // Disposable fields should be disposed
private readonly TextWriter _stdOutWriter;
@@ -908,15 +885,6 @@ public override void WriteLine(string? value)
}
}
- internal sealed class TestConsole(BaseCommandLineTest.OutputCapture outputCapture, BaseCommandLineTest.OutputCapture errorCapture) : IConsole
- {
- public IStandardStreamWriter Error { get; set; } = errorCapture;
- public IStandardStreamWriter Out { get; set; } = outputCapture;
- public bool IsOutputRedirected { get; set; }
- public bool IsErrorRedirected { get; set; }
- public bool IsInputRedirected { get; set; }
- }
-
internal sealed class CustomAnsiConsoleOutput(TextWriter writer) : IAnsiConsoleOutput
{
public TextWriter Writer { get; } = writer ?? throw new ArgumentNullException(nameof(writer));
diff --git a/MSStore.CLI.UnitTests/EmptyCommandUnitTests.cs b/MSStore.CLI.UnitTests/EmptyCommandUnitTests.cs
index 2d89731..34409f9 100644
--- a/MSStore.CLI.UnitTests/EmptyCommandUnitTests.cs
+++ b/MSStore.CLI.UnitTests/EmptyCommandUnitTests.cs
@@ -13,7 +13,7 @@ public async Task EmptyCommandShouldReturnZeroIfLoggedIn()
var result = await ParseAndInvokeAsync([]);
- result.Error.Should().Contain("CLI tool to automate Microsoft Store Developer tasks.");
+ result.Output.Should().Contain("CLI tool to automate Microsoft Store Developer tasks.");
}
[TestMethod]
diff --git a/MSStore.CLI.UnitTests/FlightsSubmissionCommandUnitTests.cs b/MSStore.CLI.UnitTests/FlightsSubmissionCommandUnitTests.cs
index d1800da..007a0a5 100644
--- a/MSStore.CLI.UnitTests/FlightsSubmissionCommandUnitTests.cs
+++ b/MSStore.CLI.UnitTests/FlightsSubmissionCommandUnitTests.cs
@@ -25,9 +25,9 @@ public async Task FlightSubmissionCommandWithNoParameter()
[
"flights",
"submission"
- ]);
+ ], 1);
- result.Error.Should().Contain("Execute flight submissions related tasks.");
+ result.Output.Should().Contain("Execute flight submissions related tasks.");
}
[TestMethod]
diff --git a/MSStore.CLI.UnitTests/MSStore.CLI.UnitTests.csproj b/MSStore.CLI.UnitTests/MSStore.CLI.UnitTests.csproj
index 9df47de..d3b751c 100644
--- a/MSStore.CLI.UnitTests/MSStore.CLI.UnitTests.csproj
+++ b/MSStore.CLI.UnitTests/MSStore.CLI.UnitTests.csproj
@@ -1,4 +1,4 @@
-
+
net9.0;net9.0-windows10.0.17763.0
@@ -44,22 +44,22 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
+
diff --git a/MSStore.CLI.UnitTests/ProjectConfiguratorFactoryTests.cs b/MSStore.CLI.UnitTests/ProjectConfiguratorFactoryTests.cs
index 0ab7a1e..b96c104 100644
--- a/MSStore.CLI.UnitTests/ProjectConfiguratorFactoryTests.cs
+++ b/MSStore.CLI.UnitTests/ProjectConfiguratorFactoryTests.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-using System.CommandLine.Hosting;
using Microsoft.Extensions.DependencyInjection;
using MSStore.CLI.ProjectConfigurators;
@@ -33,11 +32,8 @@ public async Task ProjectConfiguratorFactoryFindsURLProperly(string pathOrUrl, T
pathOrUrl = path;
}
- await RunTestAsync(async (context) =>
+ await RunTestAsync(async (parseResult, host, ct) =>
{
- var ct = context.GetCancellationToken();
-
- var host = context.GetHost();
var projectConfiguratorFactory = host.Services.GetService()!;
if (testDataProjectSubPath != null && testDataProjectSubPath.Length != 0 && path != null)
diff --git a/MSStore.CLI.UnitTests/SettingsCommandUnitTests.cs b/MSStore.CLI.UnitTests/SettingsCommandUnitTests.cs
index b7d41ff..0072eeb 100644
--- a/MSStore.CLI.UnitTests/SettingsCommandUnitTests.cs
+++ b/MSStore.CLI.UnitTests/SettingsCommandUnitTests.cs
@@ -24,8 +24,8 @@ public async Task SettingsCommandWithNoParametersShouldReturnZeroAndShowHelp()
"settings"
]);
- result.Error.Should().Contain("Usage:");
- result.Error.Should().Contain("settings [command] [options]");
+ result.Output.Should().Contain("Usage:");
+ result.Output.Should().Contain("settings [command] [options]");
}
[TestMethod]
diff --git a/MSStore.CLI.UnitTests/SubmissionCommandPackagedUnitTests.cs b/MSStore.CLI.UnitTests/SubmissionCommandPackagedUnitTests.cs
index bee5581..e50a05c 100644
--- a/MSStore.CLI.UnitTests/SubmissionCommandPackagedUnitTests.cs
+++ b/MSStore.CLI.UnitTests/SubmissionCommandPackagedUnitTests.cs
@@ -23,9 +23,9 @@ public async Task SubmissionCommandWithNoParameter()
var result = await ParseAndInvokeAsync(
[
"submission"
- ]);
+ ], 1);
- result.Error.Should().Contain("Executes commands to a store submission.");
+ result.Output.Should().Contain("Executes commands to a store submission.");
}
[TestMethod]
diff --git a/MSStore.CLI/CommandExtensions.cs b/MSStore.CLI/CommandExtensions.cs
deleted file mode 100644
index fa04117..0000000
--- a/MSStore.CLI/CommandExtensions.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using System;
-using System.CommandLine;
-using System.CommandLine.Help;
-
-namespace MSStore.CLI
-{
- internal static class CommandExtensions
- {
- public static void SetDefaultHelpHandler(this Command command)
- {
- command.SetHandler((context) =>
- {
- HelpBuilder helpBuilder = new(LocalizationResources.Instance, GetBufferWidth());
- helpBuilder.Write(command, Console.Out);
- });
- }
-
- internal static int GetBufferWidth()
- {
- try
- {
- return Console.BufferWidth;
- }
- catch
- {
- // Default to 240
- return 240;
- }
- }
- }
-}
diff --git a/MSStore.CLI/Commands/Apps/GetCommand.cs b/MSStore.CLI/Commands/Apps/GetCommand.cs
index ce22ed6..5fc7720 100644
--- a/MSStore.CLI/Commands/Apps/GetCommand.cs
+++ b/MSStore.CLI/Commands/Apps/GetCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -22,31 +23,24 @@ internal class GetCommand : Command
public GetCommand()
: base("get", "Retrieves the Application details.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ string productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
object? application = null;
@@ -54,11 +48,11 @@ public async Task InvokeAsync(InvocationContext context)
{
try
{
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Packaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Packaged)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- application = await storePackagedAPI.GetApplicationAsync(ProductId, ct);
+ application = await storePackagedAPI.GetApplicationAsync(productId, ct);
}
}
catch (MSStoreHttpException err)
@@ -95,7 +89,7 @@ public async Task InvokeAsync(InvocationContext context)
{
if (app?.Id == null)
{
- _ansiConsole.MarkupLine($"Could not find application with ID '{ProductId}'");
+ _ansiConsole.MarkupLine($"Could not find application with ID '{productId}'");
return await _telemetryClient.TrackCommandEventAsync(-1, ct);
}
else
diff --git a/MSStore.CLI/Commands/Apps/ListCommand.cs b/MSStore.CLI/Commands/Apps/ListCommand.cs
index 94bd6af..d90083f 100644
--- a/MSStore.CLI/Commands/Apps/ListCommand.cs
+++ b/MSStore.CLI/Commands/Apps/ListCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Globalization;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -21,22 +22,15 @@ public ListCommand()
{
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public int Invoke(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
- {
- var ct = context.GetCancellationToken();
-
var appList = await _ansiConsole.Status().StartAsync("Retrieving Managed Applications", async ctx =>
{
try
diff --git a/MSStore.CLI/Commands/AppsCommand.cs b/MSStore.CLI/Commands/AppsCommand.cs
index f03bdb2..61a17cb 100644
--- a/MSStore.CLI/Commands/AppsCommand.cs
+++ b/MSStore.CLI/Commands/AppsCommand.cs
@@ -8,12 +8,11 @@ namespace MSStore.CLI.Commands
{
internal class AppsCommand : Command
{
- public AppsCommand()
+ public AppsCommand(ListCommand listCommand, GetCommand getCommand)
: base("apps", "Execute apps related tasks.")
{
- AddCommand(new ListCommand());
- AddCommand(new GetCommand());
- this.SetDefaultHelpHandler();
+ Subcommands.Add(listCommand);
+ Subcommands.Add(getCommand);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/CreateCommand.cs b/MSStore.CLI/Commands/Flights/CreateCommand.cs
index c5c0415..e2ac23d 100644
--- a/MSStore.CLI/Commands/Flights/CreateCommand.cs
+++ b/MSStore.CLI/Commands/Flights/CreateCommand.cs
@@ -7,6 +7,7 @@
using System.CommandLine.Invocation;
using System.Linq;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -20,62 +21,65 @@ namespace MSStore.CLI.Commands.Flights
{
internal class CreateCommand : Command
{
- public CreateCommand()
- : base("create", "Creates a flight for the specified Application and flight.")
+ private static readonly Argument FriendlyNameArgument;
+ private static readonly Option> GroupIdsOption;
+ private static readonly Option RankHigherThanOption;
+
+ static CreateCommand()
{
- AddArgument(SubmissionCommand.ProductIdArgument);
-
- AddArgument(new Argument("friendlyName", "The friendly name of the flight."));
- var groupIdsOption = new Option>(
- aliases:
- [
- "--group-ids",
- "-g"
- ],
- getDefaultValue: Array.Empty,
- description: "The group IDs to associate with the flight.")
+ FriendlyNameArgument = new Argument("friendlyName")
+ {
+ Description = "The friendly name of the flight."
+ };
+
+ GroupIdsOption = new Option>("--group-ids", "-g")
{
+ DefaultValueFactory = _ => Array.Empty(),
+ Description = "The group IDs to associate with the flight.",
AllowMultipleArgumentsPerToken = true
};
- groupIdsOption.AddValidator((result) =>
+ GroupIdsOption.Validators.Add((result) =>
{
var groupIds = result.Tokens.Select(t => t.Value).ToList();
if (groupIds.Count == 0)
{
- result.ErrorMessage = "At least one group ID must be provided.";
+ result.AddError("At least one group ID must be provided.");
}
});
- AddOption(groupIdsOption);
+ RankHigherThanOption = new Option("--rank-higher-than", "-r")
+ {
+ Description = "The flight ID to rank higher than."
+ };
+ }
- AddOption(new Option(["--rank-higher-than", "-r"], "The flight ID to rank higher than."));
+ public CreateCommand()
+ : base("create", "Creates a flight for the specified Application and flight.")
+ {
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(FriendlyNameArgument);
+ Options.Add(GroupIdsOption);
+ Options.Add(RankHigherThanOption);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FriendlyName { get; set; } = null!;
- public IEnumerable GroupIds { get; set; } = null!;
- public string? RankHigherThan { get; set; }
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var friendlyName = parseResult.GetRequiredValue(FriendlyNameArgument);
+ var groupIds = parseResult.GetRequiredValue(GroupIdsOption);
+ var rankHigherThan = parseResult.GetValue(RankHigherThanOption);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var flight = await _ansiConsole.Status().StartAsync("Creating Flight", async ctx =>
@@ -84,7 +88,7 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flight = await storePackagedAPI.CreateFlightAsync(ProductId, FriendlyName, GroupIds.ToList(), RankHigherThan, ct);
+ var flight = await storePackagedAPI.CreateFlightAsync(productId, friendlyName, [.. groupIds], rankHigherThan, ct);
ctx.SuccessStatus(_ansiConsole, "[bold green]Created Flight[/]");
diff --git a/MSStore.CLI/Commands/Flights/DeleteCommand.cs b/MSStore.CLI/Commands/Flights/DeleteCommand.cs
index 5c54bbd..8a0886c 100644
--- a/MSStore.CLI/Commands/Flights/DeleteCommand.cs
+++ b/MSStore.CLI/Commands/Flights/DeleteCommand.cs
@@ -4,6 +4,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -20,33 +21,26 @@ internal class DeleteCommand : Command
public DeleteCommand()
: base("delete", "Deletes a flight for the specified Application and flight.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(GetCommand.FlightIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(GetCommand.FlightIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(GetCommand.FlightIdArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
return await _telemetryClient.TrackCommandEventAsync(
@@ -56,7 +50,7 @@ await _ansiConsole.Status().StartAsync("Deleting Flight", async ctx =>
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- DevCenterError? devCenterError = await storePackagedAPI.DeleteFlightAsync(ProductId, FlightId, ct);
+ DevCenterError? devCenterError = await storePackagedAPI.DeleteFlightAsync(productId, flightId, ct);
ctx.SuccessStatus(_ansiConsole, "[bold green]Deleted Flight[/]");
diff --git a/MSStore.CLI/Commands/Flights/FlightSubmissionCommand.cs b/MSStore.CLI/Commands/Flights/FlightSubmissionCommand.cs
index 99fecd7..c46f989 100644
--- a/MSStore.CLI/Commands/Flights/FlightSubmissionCommand.cs
+++ b/MSStore.CLI/Commands/Flights/FlightSubmissionCommand.cs
@@ -7,17 +7,16 @@ namespace MSStore.CLI.Commands.Flights
{
internal class FlightSubmissionCommand : Command
{
- public FlightSubmissionCommand()
+ public FlightSubmissionCommand(Submission.GetCommand getCommand, Submission.DeleteCommand deleteCommand, Submission.UpdateCommand updateCommand, Submission.PublishCommand publishCommand, Submission.PollCommand pollCommand, Submission.StatusCommand statusCommand, Submission.RolloutCommand rolloutCommand)
: base("submission", "Execute flight submissions related tasks.")
{
- AddCommand(new Submission.GetCommand());
- AddCommand(new Submission.DeleteCommand());
- AddCommand(new Submission.UpdateCommand());
- AddCommand(new Submission.PublishCommand());
- AddCommand(new Submission.PollCommand());
- AddCommand(new Submission.StatusCommand());
- AddCommand(new Submission.RolloutCommand());
- this.SetDefaultHelpHandler();
+ Subcommands.Add(getCommand);
+ Subcommands.Add(deleteCommand);
+ Subcommands.Add(updateCommand);
+ Subcommands.Add(publishCommand);
+ Subcommands.Add(pollCommand);
+ Subcommands.Add(statusCommand);
+ Subcommands.Add(rolloutCommand);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/GetCommand.cs b/MSStore.CLI/Commands/Flights/GetCommand.cs
index d3361cb..e0d4682 100644
--- a/MSStore.CLI/Commands/Flights/GetCommand.cs
+++ b/MSStore.CLI/Commands/Flights/GetCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -21,39 +22,35 @@ internal class GetCommand : Command
static GetCommand()
{
- FlightIdArgument = new Argument("flightId", "The flight Id.");
+ FlightIdArgument = new Argument("flightId")
+ {
+ Description = "The flight Id."
+ };
}
public GetCommand()
: base("get", "Retrieves a flight for the specified Application and flight.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(FlightIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(FlightIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(FlightIdArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var flight = await _ansiConsole.Status().StartAsync("Retrieving Flight", async ctx =>
@@ -62,7 +59,7 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
ctx.SuccessStatus(_ansiConsole, "[bold green]Retrieved Flight[/]");
diff --git a/MSStore.CLI/Commands/Flights/ListCommand.cs b/MSStore.CLI/Commands/Flights/ListCommand.cs
index c052283..c83e625 100644
--- a/MSStore.CLI/Commands/Flights/ListCommand.cs
+++ b/MSStore.CLI/Commands/Flights/ListCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Globalization;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -19,79 +20,73 @@ internal class ListCommand : Command
public ListCommand()
: base("list", "Retrieves all the Flights for the specified Application.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
- return await _telemetryClient.TrackCommandEventAsync(
- await _ansiConsole.Status().StartAsync("Retrieving Flights", async ctx =>
+ var flightsList = await _ansiConsole.Status().StartAsync("Retrieving Flights", async ctx =>
+ {
+ try
{
- try
- {
- var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
+ var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flightsList = await storePackagedAPI.GetFlightsAsync(ProductId, ct);
+ var flightsList = await storePackagedAPI.GetFlightsAsync(productId, ct);
- ctx.SuccessStatus(_ansiConsole, "[bold green]Retrieved Flights[/]");
+ ctx.SuccessStatus(_ansiConsole, "[bold green]Retrieved Flights[/]");
- if (flightsList?.Count > 0)
- {
- var table = new Table();
- table.AddColumns(string.Empty, "FlightId", "FriendlyName", "LastPublishedFlightSubmission.Id", "PendingFlightSubmission.Id", "GroupIds", "RankHigherThan");
+ return flightsList;
+ }
+ catch (Exception err)
+ {
+ _logger.LogError(err, "Error while retrieving Flights.");
+ ctx.ErrorStatus(_ansiConsole, err);
+ return null;
+ }
+ });
- int i = 1;
- foreach (var f in flightsList)
- {
- table.AddRow(
- i.ToString(CultureInfo.InvariantCulture),
- $"[bold u]{f.FlightId}[/]",
- $"[bold u]{f.FriendlyName}[/]",
- $"[bold u]{f.LastPublishedFlightSubmission?.Id}[/]",
- $"[bold u]{f.PendingFlightSubmission?.Id}[/]",
- $"[bold u]{string.Join(", ", f.GroupIds ?? [])}[/]",
- $"[bold u]{f.RankHigherThan}[/]");
- i++;
- }
+ if (flightsList?.Count > 0)
+ {
+ var table = new Table();
+ table.AddColumns(string.Empty, "FlightId", "FriendlyName", "LastPublishedFlightSubmission.Id", "PendingFlightSubmission.Id", "GroupIds", "RankHigherThan");
- AnsiConsole.Write(table);
- }
- else
- {
- _ansiConsole.MarkupLine("The application has [bold][u]no[/] Flights[/].");
- }
+ int i = 1;
+ foreach (var f in flightsList)
+ {
+ table.AddRow(
+ i.ToString(CultureInfo.InvariantCulture),
+ $"[bold u]{f.FlightId}[/]",
+ $"[bold u]{f.FriendlyName}[/]",
+ $"[bold u]{f.LastPublishedFlightSubmission?.Id}[/]",
+ $"[bold u]{f.PendingFlightSubmission?.Id}[/]",
+ $"[bold u]{string.Join(", ", f.GroupIds ?? [])}[/]",
+ $"[bold u]{f.RankHigherThan}[/]");
+ i++;
+ }
- return 0;
- }
- catch (Exception err)
- {
- _logger.LogError(err, "Error while retrieving Flights.");
- ctx.ErrorStatus(_ansiConsole, err);
- return -1;
- }
- }), ct);
+ AnsiConsole.Write(table);
+ return await _telemetryClient.TrackCommandEventAsync(0, ct);
+ }
+ else
+ {
+ _ansiConsole.MarkupLine("The application has [bold][u]no[/] Flights[/].");
+ return await _telemetryClient.TrackCommandEventAsync(-1, ct);
+ }
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/DeleteCommand.cs b/MSStore.CLI/Commands/Flights/Submission/DeleteCommand.cs
index 70799dc..befaac1 100644
--- a/MSStore.CLI/Commands/Flights/Submission/DeleteCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/DeleteCommand.cs
@@ -4,6 +4,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -20,12 +21,12 @@ internal class DeleteCommand : Command
public DeleteCommand()
: base("delete", "Deletes the pending package flight submission from the store.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
- AddOption(Commands.Submission.DeleteCommand.NoConfirmOption);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
+ Options.Add(Commands.Submission.DeleteCommand.NoConfirmOption);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IConsoleReader consoleReader, IBrowserLauncher browserLauncher, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IConsoleReader consoleReader, IBrowserLauncher browserLauncher, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
@@ -34,23 +35,16 @@ public DeleteCommand()
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
- public bool? NoConfirm { get; set; }
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
+ var noConfirm = parseResult.GetValue(Commands.Submission.DeleteCommand.NoConfirmOption);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
IStorePackagedAPI storePackagedAPI = null!;
@@ -61,11 +55,11 @@ public async Task InvokeAsync(InvocationContext context)
{
storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
@@ -103,18 +97,18 @@ public async Task InvokeAsync(InvocationContext context)
if (flightSubmissionId == null)
{
_ansiConsole.WriteLine("Could not find flight submission.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
_ansiConsole.WriteLine($"Found Flight Submission with Id '{flightSubmissionId}'");
- if (NoConfirm == false && !await _consoleReader.YesNoConfirmationAsync("Do you want to delete the pending flight submission?", ct))
+ if (noConfirm == false && !await _consoleReader.YesNoConfirmationAsync("Do you want to delete the pending flight submission?", ct))
{
return -2;
}
- var success = await storePackagedAPI.DeleteSubmissionAsync(_ansiConsole, ProductId, FlightId, flightSubmissionId, _browserLauncher, _logger, ct);
+ var success = await storePackagedAPI.DeleteSubmissionAsync(_ansiConsole, productId, flightId, flightSubmissionId, _browserLauncher, _logger, ct);
- return await _telemetryClient.TrackCommandEventAsync(ProductId, success ? 0 : -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, success ? 0 : -1, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/GetCommand.cs b/MSStore.CLI/Commands/Flights/Submission/GetCommand.cs
index 450c618..8f1ebd5 100644
--- a/MSStore.CLI/Commands/Flights/Submission/GetCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/GetCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -21,33 +22,26 @@ internal class GetCommand : Command
public GetCommand()
: base("get", "Retrieves the existing package flight submission, either the existing draft or the last published one.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var flightSubmission = await _ansiConsole.Status().StartAsync("Retrieving Flight Submission", async ctx =>
@@ -56,15 +50,15 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
- return await storePackagedAPI.GetAnyFlightSubmissionAsync(_ansiConsole, ProductId, flight, ctx, _logger, ct);
+ return await storePackagedAPI.GetAnyFlightSubmissionAsync(_ansiConsole, productId, flight, ctx, _logger, ct);
}
catch (MSStoreHttpException err)
{
@@ -91,12 +85,12 @@ public async Task InvokeAsync(InvocationContext context)
if (flightSubmission == null)
{
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
AnsiConsole.WriteLine(JsonSerializer.Serialize(flightSubmission, SourceGenerationContext.GetCustom(true).DevCenterFlightSubmission));
- return await _telemetryClient.TrackCommandEventAsync(ProductId, 0, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, 0, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/PollCommand.cs b/MSStore.CLI/Commands/Flights/Submission/PollCommand.cs
index 4536552..240ec25 100644
--- a/MSStore.CLI/Commands/Flights/Submission/PollCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/PollCommand.cs
@@ -4,6 +4,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -20,11 +21,11 @@ internal class PollCommand : Command
public PollCommand()
: base("poll", "Polls until the existing flight submission is PUBLISHED or FAILED.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient, IBrowserLauncher browserLauncher) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient, IBrowserLauncher browserLauncher) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
@@ -32,27 +33,20 @@ public PollCommand()
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
private readonly IBrowserLauncher _browserLauncher = browserLauncher ?? throw new ArgumentNullException(nameof(browserLauncher));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
IStorePackagedAPI? storePackagedAPI = null;
DevCenterFlight? flight = null;
ApplicationSubmissionInfo? flightSubmission = null;
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
DevCenterSubmissionStatusResponse? lastSubmissionStatus = await _ansiConsole.Status().StartAsync("Polling flight submission status", async ctx =>
@@ -61,11 +55,11 @@ public async Task InvokeAsync(InvocationContext context)
{
storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
@@ -73,11 +67,11 @@ public async Task InvokeAsync(InvocationContext context)
if (flightSubmission?.Id == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find flight submission for application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find flight submission for application flight with ID '{productId}'/'{flightId}'");
return null;
}
- var lastSubmissionStatus = await storePackagedAPI.PollSubmissionStatusAsync(ansiConsole, ProductId, flight.FlightId, flightSubmission.Id, false, _logger, ct: ct);
+ var lastSubmissionStatus = await storePackagedAPI.PollSubmissionStatusAsync(ansiConsole, productId, flight.FlightId, flightSubmission.Id, false, _logger, ct: ct);
ctx.SuccessStatus(_ansiConsole);
@@ -95,12 +89,12 @@ public async Task InvokeAsync(InvocationContext context)
if (lastSubmissionStatus != null && storePackagedAPI != null && flight?.FlightId != null && flightSubmission?.Id != null)
{
return await _telemetryClient.TrackCommandEventAsync(
- ProductId,
- await storePackagedAPI.HandleLastSubmissionStatusAsync(_ansiConsole, lastSubmissionStatus, ProductId, flight.FlightId, flightSubmission.Id, _browserLauncher, _logger, ct),
+ productId,
+ await storePackagedAPI.HandleLastSubmissionStatusAsync(_ansiConsole, lastSubmissionStatus, productId, flight.FlightId, flightSubmission.Id, _browserLauncher, _logger, ct),
ct);
}
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/PublishCommand.cs b/MSStore.CLI/Commands/Flights/Submission/PublishCommand.cs
index 81a4787..0d056a6 100644
--- a/MSStore.CLI/Commands/Flights/Submission/PublishCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/PublishCommand.cs
@@ -4,6 +4,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -19,48 +20,41 @@ internal class PublishCommand : Command
public PublishCommand()
: base("publish", "Starts the flight submission process for the existing Draft.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
return await _telemetryClient.TrackCommandEventAsync(
- ProductId,
+ productId,
await _ansiConsole.Status().StartAsync("Publishing flight submission", async ctx =>
{
try
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return -1;
}
@@ -68,11 +62,11 @@ await _ansiConsole.Status().StartAsync("Publishing flight submission", async ctx
if (flightSubmission?.Id == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find flight submission for application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find flight submission for application flight with ID '{productId}'/'{flightId}'");
return -1;
}
- var flightSubmissionCommit = await storePackagedAPI.CommitFlightSubmissionAsync(ProductId, FlightId, flightSubmission.Id, ct);
+ var flightSubmissionCommit = await storePackagedAPI.CommitFlightSubmissionAsync(productId, flightId, flightSubmission.Id, ct);
if (flightSubmissionCommit == null)
{
@@ -85,7 +79,7 @@ await _ansiConsole.Status().StartAsync("Publishing flight submission", async ctx
return 0;
}
- ctx.ErrorStatus(_ansiConsole, $"Could not commit flight submission for application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not commit flight submission for application flight with ID '{productId}'/'{flightId}'");
_ansiConsole.MarkupLine($"[red]{flightSubmissionCommit.ToErrorMessage()}[/]");
return -1;
diff --git a/MSStore.CLI/Commands/Flights/Submission/Rollout/FinalizeCommand.cs b/MSStore.CLI/Commands/Flights/Submission/Rollout/FinalizeCommand.cs
index f91130a..e07e642 100644
--- a/MSStore.CLI/Commands/Flights/Submission/Rollout/FinalizeCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/Rollout/FinalizeCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -21,35 +22,28 @@ internal class FinalizeCommand : Command
public FinalizeCommand()
: base("finalize", "Finalizes the flight rollout of a submission.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
- AddOption(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
+ Options.Add(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
- public string? SubmissionId { get; set; }
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
+ var submissionId = parseResult.GetValue(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var flightSubmissionRollout = await _ansiConsole.Status().StartAsync("Finalizing Flight Submission Rollout", async ctx =>
@@ -58,26 +52,26 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- if (SubmissionId == null)
+ if (submissionId == null)
{
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
- SubmissionId = flight.GetAnyFlightSubmissionId();
+ submissionId = flight.GetAnyFlightSubmissionId();
- if (SubmissionId == null)
+ if (submissionId == null)
{
ctx.ErrorStatus(_ansiConsole, "Could not find the flight submission. Please check the ProductId/FlightId.");
return null;
}
}
- return await storePackagedAPI.FinalizePackageRolloutAsync(ProductId, SubmissionId, FlightId, ct);
+ return await storePackagedAPI.FinalizePackageRolloutAsync(productId, submissionId, flightId, ct);
}
catch (MSStoreHttpException err)
{
@@ -104,12 +98,12 @@ public async Task InvokeAsync(InvocationContext context)
if (flightSubmissionRollout == null)
{
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
AnsiConsole.WriteLine(JsonSerializer.Serialize(flightSubmissionRollout, SourceGenerationContext.GetCustom(true).PackageRollout));
- return await _telemetryClient.TrackCommandEventAsync(ProductId, 0, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, 0, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/Rollout/GetCommand.cs b/MSStore.CLI/Commands/Flights/Submission/Rollout/GetCommand.cs
index aadb7e6..d0e3625 100644
--- a/MSStore.CLI/Commands/Flights/Submission/Rollout/GetCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/Rollout/GetCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -21,35 +22,28 @@ internal class GetCommand : Command
public GetCommand()
: base("get", "Retrieves the flight rollout status of a submission.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
- AddOption(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
+ Options.Add(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
- public string? SubmissionId { get; set; }
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
+ var submissionId = parseResult.GetValue(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var flightSubmissionRollout = await _ansiConsole.Status().StartAsync("Retrieving Flight Submission Rollout", async ctx =>
@@ -58,26 +52,26 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- if (SubmissionId == null)
+ if (submissionId == null)
{
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
- SubmissionId = flight.GetAnyFlightSubmissionId();
+ submissionId = flight.GetAnyFlightSubmissionId();
- if (SubmissionId == null)
+ if (submissionId == null)
{
ctx.ErrorStatus(_ansiConsole, "Could not find the flight submission. Please check the ProductId/FlightId.");
return null;
}
}
- return await storePackagedAPI.GetPackageRolloutAsync(ProductId, SubmissionId, FlightId, ct);
+ return await storePackagedAPI.GetPackageRolloutAsync(productId, submissionId, flightId, ct);
}
catch (MSStoreHttpException err)
{
@@ -104,12 +98,12 @@ public async Task InvokeAsync(InvocationContext context)
if (flightSubmissionRollout == null)
{
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
AnsiConsole.WriteLine(JsonSerializer.Serialize(flightSubmissionRollout, SourceGenerationContext.GetCustom(true).PackageRollout));
- return await _telemetryClient.TrackCommandEventAsync(ProductId, 0, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, 0, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/Rollout/HaltCommand.cs b/MSStore.CLI/Commands/Flights/Submission/Rollout/HaltCommand.cs
index 2ca7656..b7316d4 100644
--- a/MSStore.CLI/Commands/Flights/Submission/Rollout/HaltCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/Rollout/HaltCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -21,35 +22,28 @@ internal class HaltCommand : Command
public HaltCommand()
: base("halt", "Halts the flight rollout of a submission.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
- AddOption(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
+ Options.Add(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
- public string? SubmissionId { get; set; }
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
+ var submissionId = parseResult.GetValue(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var flightSubmissionRollout = await _ansiConsole.Status().StartAsync("Halting Flight Submission Rollout", async ctx =>
@@ -58,26 +52,26 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- if (SubmissionId == null)
+ if (submissionId == null)
{
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
- SubmissionId = flight.GetAnyFlightSubmissionId();
+ submissionId = flight.GetAnyFlightSubmissionId();
- if (SubmissionId == null)
+ if (submissionId == null)
{
ctx.ErrorStatus(_ansiConsole, "Could not find the flight submission. Please check the ProductId/FlightId.");
return null;
}
}
- return await storePackagedAPI.HaltPackageRolloutAsync(ProductId, SubmissionId, FlightId, ct);
+ return await storePackagedAPI.HaltPackageRolloutAsync(productId, submissionId, flightId, ct);
}
catch (MSStoreHttpException err)
{
@@ -104,12 +98,12 @@ public async Task InvokeAsync(InvocationContext context)
if (flightSubmissionRollout == null)
{
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
AnsiConsole.WriteLine(JsonSerializer.Serialize(flightSubmissionRollout, SourceGenerationContext.GetCustom(true).PackageRollout));
- return await _telemetryClient.TrackCommandEventAsync(ProductId, 0, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, 0, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/Rollout/UpdateCommand.cs b/MSStore.CLI/Commands/Flights/Submission/Rollout/UpdateCommand.cs
index bebd214..767bd01 100644
--- a/MSStore.CLI/Commands/Flights/Submission/Rollout/UpdateCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/Rollout/UpdateCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -18,50 +19,49 @@ namespace MSStore.CLI.Commands.Flights.Submission.Rollout
{
internal class UpdateCommand : Command
{
+ private static readonly Argument PercentageArgument;
+
+ static UpdateCommand()
+ {
+ PercentageArgument = new Argument("percentage")
+ {
+ Description = "The percentage of users that will receive the submission rollout."
+ };
+ }
+
public UpdateCommand()
: base("update", "Update the flight rollout percentage of a submission.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
- AddOption(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
-
- var percentage = new Argument(
- "percentage",
- description: "The percentage of users that will receive the submission rollout.");
- AddArgument(percentage);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
+ Options.Add(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
+ Arguments.Add(PercentageArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
- public string? SubmissionId { get; set; }
- public float Percentage { get; set; }
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
+ var submissionId = parseResult.GetValue(Commands.Submission.Rollout.GetCommand.SubmissionIdOption);
+ var percentage = parseResult.GetRequiredValue(PercentageArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
- if (Percentage < 0 || Percentage > 100)
+ if (percentage < 0 || percentage > 100)
{
_ansiConsole.WriteLine("The percentage must be between 0 and 100.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var flightSubmissionRollout = await _ansiConsole.Status().StartAsync("Updating Flight Submission Rollout", async ctx =>
@@ -70,26 +70,26 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- if (SubmissionId == null)
+ if (submissionId == null)
{
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
- SubmissionId = flight.GetAnyFlightSubmissionId();
+ submissionId = flight.GetAnyFlightSubmissionId();
- if (SubmissionId == null)
+ if (submissionId == null)
{
ctx.ErrorStatus(_ansiConsole, "Could not find the flight submission. Please check the ProductId/FlightId.");
return null;
}
}
- return await storePackagedAPI.UpdatePackageRolloutPercentageAsync(ProductId, SubmissionId, FlightId, Percentage, ct);
+ return await storePackagedAPI.UpdatePackageRolloutPercentageAsync(productId, submissionId, flightId, percentage, ct);
}
catch (MSStoreHttpException err)
{
@@ -116,12 +116,12 @@ public async Task InvokeAsync(InvocationContext context)
if (flightSubmissionRollout == null)
{
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
AnsiConsole.WriteLine(JsonSerializer.Serialize(flightSubmissionRollout, SourceGenerationContext.GetCustom(true).PackageRollout));
- return await _telemetryClient.TrackCommandEventAsync(ProductId, 0, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, 0, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/RolloutCommand.cs b/MSStore.CLI/Commands/Flights/Submission/RolloutCommand.cs
index f170646..7500ee9 100644
--- a/MSStore.CLI/Commands/Flights/Submission/RolloutCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/RolloutCommand.cs
@@ -7,14 +7,13 @@ namespace MSStore.CLI.Commands.Flights.Submission
{
internal class RolloutCommand : Command
{
- public RolloutCommand()
+ public RolloutCommand(Rollout.GetCommand getCommand, Rollout.UpdateCommand updateCommand, Rollout.HaltCommand haltCommand, Rollout.FinalizeCommand finalizeCommand)
: base("rollout", "Execute flight rollout related operations")
{
- AddCommand(new Rollout.GetCommand());
- AddCommand(new Rollout.UpdateCommand());
- AddCommand(new Rollout.HaltCommand());
- AddCommand(new Rollout.FinalizeCommand());
- this.SetDefaultHelpHandler();
+ Subcommands.Add(getCommand);
+ Subcommands.Add(updateCommand);
+ Subcommands.Add(haltCommand);
+ Subcommands.Add(finalizeCommand);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/StatusCommand.cs b/MSStore.CLI/Commands/Flights/Submission/StatusCommand.cs
index 120baf7..f09cc6d 100644
--- a/MSStore.CLI/Commands/Flights/Submission/StatusCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/StatusCommand.cs
@@ -4,6 +4,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -19,33 +20,26 @@ internal class StatusCommand : Command
public StatusCommand()
: base("status", "Retrieves the current status of the store flight submission.")
{
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
var devCenterFlightSubmission = await _ansiConsole.Status().StartAsync("Retrieving flight submission status", async ctx =>
@@ -54,15 +48,15 @@ public async Task InvokeAsync(InvocationContext context)
{
var storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ ctx.ErrorStatus(_ansiConsole, $"Could not find application flight with ID '{productId}'/'{flightId}'");
return null;
}
- return await storePackagedAPI.GetAnyFlightSubmissionAsync(_ansiConsole, ProductId, flight, ctx, _logger, ct);
+ return await storePackagedAPI.GetAnyFlightSubmissionAsync(_ansiConsole, productId, flight, ctx, _logger, ct);
}
catch (Exception err)
{
@@ -74,7 +68,7 @@ public async Task InvokeAsync(InvocationContext context)
if (devCenterFlightSubmission?.Id == null)
{
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
if (devCenterFlightSubmission.Status != null)
@@ -82,9 +76,9 @@ public async Task InvokeAsync(InvocationContext context)
ansiConsole.MarkupLine($"Submission Status = [green]{devCenterFlightSubmission.Status}[/]");
}
- devCenterFlightSubmission.StatusDetails?.PrintAllTables(_ansiConsole, ProductId, devCenterFlightSubmission.Id, _logger);
+ devCenterFlightSubmission.StatusDetails?.PrintAllTables(_ansiConsole, productId, devCenterFlightSubmission.Id, _logger);
- return await _telemetryClient.TrackCommandEventAsync(ProductId, 0, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, 0, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/Flights/Submission/UpdateCommand.cs b/MSStore.CLI/Commands/Flights/Submission/UpdateCommand.cs
index 5758f71..67e0e90 100644
--- a/MSStore.CLI/Commands/Flights/Submission/UpdateCommand.cs
+++ b/MSStore.CLI/Commands/Flights/Submission/UpdateCommand.cs
@@ -5,6 +5,7 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -19,47 +20,44 @@ namespace MSStore.CLI.Commands.Flights.Submission
{
internal class UpdateCommand : Command
{
+ private static readonly Argument ProductArgument;
+
+ static UpdateCommand()
+ {
+ ProductArgument = new Argument("product")
+ {
+ Description = "The updated JSON product representation."
+ };
+ }
+
public UpdateCommand()
: base("update", "Updates the existing flight draft with the provided JSON.")
{
- var product = new Argument(
- "product",
- description: "The updated JSON product representation.");
-
- AddArgument(SubmissionCommand.ProductIdArgument);
- AddArgument(Flights.GetCommand.FlightIdArgument);
- AddArgument(product);
- AddOption(SubmissionCommand.SkipInitialPolling);
+ Arguments.Add(SubmissionCommand.ProductIdArgument);
+ Arguments.Add(Flights.GetCommand.FlightIdArgument);
+ Arguments.Add(ProductArgument);
}
- public new class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : ICommandHandler
+ public class Handler(ILogger logger, IStoreAPIFactory storeAPIFactory, IAnsiConsole ansiConsole, TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IStoreAPIFactory _storeAPIFactory = storeAPIFactory ?? throw new ArgumentNullException(nameof(storeAPIFactory));
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string Product { get; set; } = null!;
- public bool SkipInitialPolling { get; set; }
- public string ProductId { get; set; } = null!;
- public string FlightId { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
- {
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- var ct = context.GetCancellationToken();
+ var productId = parseResult.GetRequiredValue(SubmissionCommand.ProductIdArgument);
+ var flightId = parseResult.GetRequiredValue(Flights.GetCommand.FlightIdArgument);
+ var product = parseResult.GetRequiredValue(ProductArgument);
- if (ProductTypeHelper.Solve(ProductId) == ProductType.Unpackaged)
+ if (ProductTypeHelper.Solve(productId) == ProductType.Unpackaged)
{
_ansiConsole.WriteLine("This command is not supported for unpackaged applications.");
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
- var updateFlightSubmission = JsonSerializer.Deserialize(Product, SourceGenerationContext.GetCustom().DevCenterFlightSubmissionUpdate);
+ var updateFlightSubmission = JsonSerializer.Deserialize(product, SourceGenerationContext.GetCustom().DevCenterFlightSubmissionUpdate);
if (updateFlightSubmission == null)
{
@@ -74,11 +72,11 @@ public async Task InvokeAsync(InvocationContext context)
{
storePackagedAPI = await _storeAPIFactory.CreatePackagedAsync(ct: ct);
- var flight = await storePackagedAPI.GetFlightAsync(ProductId, FlightId, ct);
+ var flight = await storePackagedAPI.GetFlightAsync(productId, flightId, ct);
if (flight?.FlightId == null)
{
- throw new MSStoreException($"Could not find application flight with ID '{ProductId}'/'{FlightId}'");
+ throw new MSStoreException($"Could not find application flight with ID '{productId}'/'{flightId}'");
}
return flight;
@@ -102,7 +100,7 @@ public async Task InvokeAsync(InvocationContext context)
{
_ansiConsole.MarkupLine("Could not find an existing flight submission. [b green]Creating new flight submission[/].");
- var flightSubmission = await storePackagedAPI.CreateNewFlightSubmissionAsync(_ansiConsole, ProductId, FlightId, _logger, ct);
+ var flightSubmission = await storePackagedAPI.CreateNewFlightSubmissionAsync(_ansiConsole, productId, flightId, _logger, ct);
submissionId = flightSubmission?.Id;
if (submissionId == null)
@@ -115,7 +113,7 @@ public async Task InvokeAsync(InvocationContext context)
{
try
{
- return await storePackagedAPI.UpdateFlightSubmissionAsync(ProductId, FlightId, submissionId, updateFlightSubmission, ct);
+ return await storePackagedAPI.UpdateFlightSubmissionAsync(productId, flightId, submissionId, updateFlightSubmission, ct);
}
catch (Exception err)
{
@@ -127,12 +125,12 @@ public async Task InvokeAsync(InvocationContext context)
if (updatedFlightSubmission == null)
{
- return await _telemetryClient.TrackCommandEventAsync(ProductId, -1, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, -1, ct);
}
AnsiConsole.WriteLine(JsonSerializer.Serialize(updatedFlightSubmission, SourceGenerationContext.GetCustom(true).DevCenterFlightSubmission));
- return await _telemetryClient.TrackCommandEventAsync(ProductId, 0, ct);
+ return await _telemetryClient.TrackCommandEventAsync(productId, 0, ct);
}
}
}
diff --git a/MSStore.CLI/Commands/FlightsCommand.cs b/MSStore.CLI/Commands/FlightsCommand.cs
index 36b587e..ee6b715 100644
--- a/MSStore.CLI/Commands/FlightsCommand.cs
+++ b/MSStore.CLI/Commands/FlightsCommand.cs
@@ -8,15 +8,14 @@ namespace MSStore.CLI.Commands
{
internal class FlightsCommand : Command
{
- public FlightsCommand()
+ public FlightsCommand(ListCommand listCommand, GetCommand getCommand, DeleteCommand deleteCommand, CreateCommand createCommand, FlightSubmissionCommand flightSubmissionCommand)
: base("flights", "Execute flights related tasks.")
{
- AddCommand(new ListCommand());
- AddCommand(new GetCommand());
- AddCommand(new DeleteCommand());
- AddCommand(new CreateCommand());
- AddCommand(new FlightSubmissionCommand());
- this.SetDefaultHelpHandler();
+ Subcommands.Add(listCommand);
+ Subcommands.Add(getCommand);
+ Subcommands.Add(deleteCommand);
+ Subcommands.Add(createCommand);
+ Subcommands.Add(flightSubmissionCommand);
}
}
}
diff --git a/MSStore.CLI/Commands/InfoCommand.cs b/MSStore.CLI/Commands/InfoCommand.cs
index 3eee5c0..d4fe0f7 100644
--- a/MSStore.CLI/Commands/InfoCommand.cs
+++ b/MSStore.CLI/Commands/InfoCommand.cs
@@ -4,6 +4,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.Logging;
@@ -20,21 +21,14 @@ public InfoCommand()
{
}
- public new class Handler(IConfigurationManager configurationManager, TelemetryClient telemetryClient, ILogger logger) : ICommandHandler
+ public class Handler(IConfigurationManager configurationManager, TelemetryClient telemetryClient, ILogger logger) : AsynchronousCommandLineAction
{
private readonly IConfigurationManager _configurationManager = configurationManager ?? throw new ArgumentNullException(nameof(configurationManager));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- public int Invoke(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
- {
- var ct = context.GetCancellationToken();
-
var config = await _configurationManager.LoadAsync(ct: ct);
var table = new Table
@@ -58,7 +52,7 @@ public async Task InvokeAsync(InvocationContext context)
table.AddRow($"[bold u]Certificate Path[/]", $"[bold u]{config.CertificateFilePath}[/]");
}
- bool verbose = context.ParseResult.IsVerbose();
+ bool verbose = parseResult.IsVerbose();
if (verbose && !string.IsNullOrEmpty(config.StoreApiServiceUrl))
{
diff --git a/MSStore.CLI/Commands/InitCommand.cs b/MSStore.CLI/Commands/InitCommand.cs
index 405ab44..f0f31f4 100644
--- a/MSStore.CLI/Commands/InitCommand.cs
+++ b/MSStore.CLI/Commands/InitCommand.cs
@@ -26,15 +26,22 @@ namespace MSStore.CLI.Commands
{
internal class InitCommand : Command
{
- internal static readonly Argument PathOrUrl;
- internal static readonly Option Output;
- internal static readonly Option> Arch;
- internal static readonly Option Version;
+ internal static readonly Argument PathOrUrlArgument;
+ private static readonly Option PublisherDisplayNameOption;
+ private static readonly Option PackageOption;
+ private static readonly Option PublishOption;
+ internal static readonly Option OutputOption;
+ internal static readonly Option> ArchOption;
+ internal static readonly Option VersionOption;
static InitCommand()
{
- PathOrUrl = new Argument("pathOrUrl", () => Directory.GetCurrentDirectory().ToString(), "The root directory path where the project file is, or a public URL that points to a PWA.");
- PathOrUrl.AddValidator((result) =>
+ PathOrUrlArgument = new Argument("pathOrUrl")
+ {
+ DefaultValueFactory = _ => Directory.GetCurrentDirectory().ToString(),
+ Description = "The root directory path where the project file is, or a public URL that points to a PWA.",
+ };
+ PathOrUrlArgument.Validators.Add((result) =>
{
var pathOrUrl = result.Tokens.SingleOrDefault()?.Value ?? Directory.GetCurrentDirectory().ToString();
@@ -60,38 +67,41 @@ bool IsUri()
FileInfo? filePath = new FileInfo(pathOrUrl);
if (!filePath.Exists)
{
- result.ErrorMessage = $"File or directory does not exist: '{pathOrUrl}'.{Environment.NewLine}";
+ result.AddError($"File or directory does not exist: '{pathOrUrl}'.{Environment.NewLine}");
}
}
}
});
- Output = new Option(
- aliases:
- [
- "--output",
- "-o"
- ],
- description: "The output directory where the packaged app will be stored. If not provided, the default directory for each different type of app will be used.");
-
- Arch = new Option>(
- aliases:
- [
- "--arch",
- "-a"
- ],
- description: "The architecture(s) to build for. If not provided, the default architecture for the current OS, and project type, will be used.")
+ PublisherDisplayNameOption = new Option("--publisherDisplayName", "-n")
+ {
+ Description = "The Publisher Display Name used to configure the application. If provided, avoids an extra APIs call."
+ };
+
+ PackageOption = new Option("--package")
+ {
+ Description = "If supported by the app type, automatically packs the project."
+ };
+
+ PublishOption = new Option("--publish")
+ {
+ Description = "If supported by the app type, automatically publishes the project. Implies '--package true'"
+ };
+
+ OutputOption = new Option("--output", "-o")
{
- AllowMultipleArgumentsPerToken = true,
+ Description = "The output directory where the packaged app will be stored. If not provided, the default directory for each different type of app will be used."
};
- Version = new Option(
- aliases:
- [
- "--version",
- "-ver"
- ],
- parseArgument: result =>
+ ArchOption = new Option>("--arch", "-a")
+ {
+ Description = "The architecture(s) to build for. If not provided, the default architecture for the current OS, and project type, will be used.",
+ AllowMultipleArgumentsPerToken = true
+ };
+
+ VersionOption = new Option("--version", "-ver")
+ {
+ CustomParser = result =>
{
var version = result.Tokens.Single().Value;
if (System.Version.TryParse(version, out var parsedVersion))
@@ -99,57 +109,28 @@ bool IsUri()
return parsedVersion;
}
- result.ErrorMessage = $"Invalid version: '{version}'.{Environment.NewLine}";
+ result.AddError($"Invalid version: '{version}'.{Environment.NewLine}");
return null;
},
- description: "The version used when building the app. If not provided, the version from the project file will be used.");
+ Description = "The version used when building the app. If not provided, the version from the project file will be used."
+ };
}
public InitCommand()
: base("init", "Helps you setup your application to publish to the Microsoft Store.")
{
- AddArgument(PathOrUrl);
-
- var publisherDisplayName = new Option(
- aliases:
- [
- "--publisherDisplayName",
- "-n"
- ],
- description: "The Publisher Display Name used to configure the application. If provided, avoids an extra APIs call.");
-
- AddOption(publisherDisplayName);
-
- var package = new Option(
- aliases:
- [
- "--package"
- ],
- description: "If supported by the app type, automatically packs the project.");
-
- AddOption(package);
-
- var publish = new Option(
- aliases:
- [
- "--publish"
- ],
- description: "If supported by the app type, automatically publishes the project. Implies '--package true'");
-
- AddOption(publish);
-
- AddOption(PublishCommand.FlightIdOption);
-
- AddOption(Output);
-
- AddOption(Arch);
-
- AddOption(Version);
-
- AddOption(PublishCommand.PackageRolloutPercentageOption);
+ Arguments.Add(PathOrUrlArgument);
+ Options.Add(PublisherDisplayNameOption);
+ Options.Add(PackageOption);
+ Options.Add(PublishOption);
+ Options.Add(PublishCommand.FlightIdOption);
+ Options.Add(OutputOption);
+ Options.Add(ArchOption);
+ Options.Add(VersionOption);
+ Options.Add(PublishCommand.PackageRolloutPercentageOption);
}
- public new class Handler(
+ public class Handler(
ILogger logger,
IBrowserLauncher browserLauncher,
IConsoleReader consoleReader,
@@ -160,7 +141,7 @@ public InitCommand()
IImageConverter imageConverter,
IConfigurationManager configurationManager,
IAnsiConsole ansiConsole,
- TelemetryClient telemetryClient) : ICommandHandler
+ TelemetryClient telemetryClient) : AsynchronousCommandLineAction
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IBrowserLauncher _browserLauncher = browserLauncher ?? throw new ArgumentNullException(nameof(browserLauncher));
@@ -174,65 +155,50 @@ public InitCommand()
private readonly IAnsiConsole _ansiConsole = ansiConsole ?? throw new ArgumentNullException(nameof(ansiConsole));
private readonly TelemetryClient _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
- public string PathOrUrl { get; set; } = null!;
-
- public string? PublisherDisplayName { get; set; } = null!;
-
- public bool? Package { get; set; }
-
- public bool? Publish { get; set; }
-
- public string? FlightId { get; set; }
-
- public Version? Version { get; set; } = null!;
-
- public float? PackageRolloutPercentage { get; set; }
-
- public DirectoryInfo? Output { get; set; } = null!;
-
- public IEnumerable? Arch { get; set; } = null!;
-
- public int Invoke(InvocationContext context)
+ public override async Task InvokeAsync(ParseResult parseResult, CancellationToken ct = default)
{
- return -1001;
- }
-
- public async Task InvokeAsync(InvocationContext context)
- {
- var ct = context.GetCancellationToken();
-
- var configurator = await _projectConfiguratorFactory.FindProjectConfiguratorAsync(PathOrUrl, ct);
+ var pathOrUrl = parseResult.GetRequiredValue(PathOrUrlArgument);
+ var publisherDisplayName = parseResult.GetValue(PublisherDisplayNameOption);
+ var package = parseResult.GetValue(PackageOption);
+ var publish = parseResult.GetValue(PublishOption);
+ var flightId = parseResult.GetValue(PublishCommand.FlightIdOption);
+ var version = parseResult.GetValue(VersionOption);
+ var packageRolloutPercentage = parseResult.GetValue(PublishCommand.PackageRolloutPercentageOption);
+ var output = parseResult.GetValue(OutputOption);
+ var arch = parseResult.GetValue(ArchOption);
+
+ var configurator = await _projectConfiguratorFactory.FindProjectConfiguratorAsync(pathOrUrl, ct);
var props = new Dictionary