Skip to content

feat: use System.CommandLine to create a CLI application #1898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Tools/LambdaTestTool-v2/AWS.Lambda.TestTool.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Solution>
<Folder Name="/src/">
<Project Path="src\Amazon.Lambda.TestTool\Amazon.Lambda.TestTool.csproj" Type="Classic C#" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests\Amazon.Lambda.TestTool.UnitTests\Amazon.Lambda.TestTool.UnitTests.csproj" Type="Classic C#" />
</Folder>
</Solution>
36 changes: 0 additions & 36 deletions Tools/LambdaTestTool-v2/aws-lambda-test-tool-v2.sln

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Blazored.Modal" Version="7.3.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.11" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="Blazored.Modal" Version="7.3.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.11" />
</ItemGroup>

<ItemGroup>
Expand Down
15 changes: 15 additions & 0 deletions Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/AppRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.CommandLine;
using System.Text;

namespace Amazon.Lambda.TestTool;

public class AppRunner(
ICommandFactory commandFactory)
{
public async Task<int> Run(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;

return await commandFactory.BuildRootCommand().InvokeAsync(args);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System.CommandLine;
using System.Diagnostics;
using Amazon.Lambda.TestTool.Extensions;
using Amazon.Lambda.TestTool.Models;
using Amazon.Lambda.TestTool.Processes;
using Amazon.Lambda.TestTool.Services;

namespace Amazon.Lambda.TestTool;

public interface ICommandFactory
{
Command BuildRootCommand();
}

public class CommandFactory(
IToolInteractiveService toolInteractiveService) : ICommandFactory
{
private static readonly object RootCommandLock = new();

public Command BuildRootCommand()
{
// Name is important to set here to show correctly in the CLI usage help.
var rootCommand = new RootCommand
{
Name = "lambda-test-tool",
Description = Constants.ProductName,
};

Option<string> hostOption = new("--host", () => Constants.DefaultHost, "The hostname or IP address used for the test tool's web interface. Any host other than an explicit IP address or localhost (e.g. '*', '+' or 'example.com') binds to all public IPv4 and IPv6 addresses.");
Option<int> portOption = new("--port", () => Constants.DefaultPort,"The port number used for the test tool's web interface.");
Option<bool> noLaunchWindowOption = new("--no-launch-window","Disable auto launching the test tool's web interface in a browser.");
Option<bool> pauseExitOption = new("--pause-exit",() => true, "If set to true the test tool will pause waiting for a key input before exiting. The is useful when executing from an IDE so you can avoid having the output window immediately disappear after executing the Lambda code. The default value is true.");
Option<bool> disableLogsOption = new("--disable-logs",() => false);

lock (RootCommandLock)
{
rootCommand.Add(hostOption);
rootCommand.Add(portOption);
rootCommand.Add(noLaunchWindowOption);
rootCommand.Add(pauseExitOption);
rootCommand.Add(disableLogsOption);
}

rootCommand.SetHandler(async (context) =>
{
try
{
var lambdaOptions = new ApplicationOptions
{
Host = context.ParseResult.GetValueForOption(hostOption) ?? Constants.DefaultHost,
Port = context.ParseResult.GetValueForOption(portOption),
NoLaunchWindow = context.ParseResult.GetValueForOption(noLaunchWindowOption),
PauseExit = context.ParseResult.GetValueForOption(pauseExitOption),
DisableLogs = context.ParseResult.GetValueForOption(disableLogsOption)
};

var process = TestToolProcess.Startup(lambdaOptions);

if (!lambdaOptions.NoLaunchWindow)
{
try
{
var info = new ProcessStartInfo
{
UseShellExecute = true,
FileName = process.ServiceUrl
};
Process.Start(info);
}
catch (Exception e)
{
toolInteractiveService.WriteErrorLine($"Error launching browser: {e.Message}");
}
}

await process.RunningTask;

context.ExitCode = CommandReturnCodes.Success;
}
catch (Exception e) when (e.IsExpectedException())
{
toolInteractiveService.WriteErrorLine(string.Empty);
toolInteractiveService.WriteErrorLine(e.Message);

context.ExitCode = CommandReturnCodes.UserError;
}
catch (Exception e)
{
// This is a bug
toolInteractiveService.WriteErrorLine(
$"Unhandled exception.{Environment.NewLine}" +
$"This is a bug.{Environment.NewLine}" +
$"Please copy the stack trace below and file a bug at {Constants.LinkGithubRepo}. " +
e.PrettyPrint());

context.ExitCode = CommandReturnCodes.UnhandledException;
}
});

return rootCommand;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link href="app.css" rel="stylesheet" />

<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="Amazon.Lambda.TestTool.styles.css" />
<link rel="icon" type="image/ico" href="favicon.ico" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@inherits LayoutComponentBase
@using Amazon.Lambda.TestTool.Utilities
@inherits LayoutComponentBase

<div class="page">
<div class="sidebar">
Expand All @@ -10,7 +11,7 @@
@Body
<hr />
<footer>
<p>@Constants.PRODUCT_NAME (@Utils.DetermineToolVersion()) is an open source project. For issues or feedback visit the <a href="@Constants.LINK_GITHUB_TEST_TOOL">AWS Lambda for .NET Core GitHub repository.</a></p>
<p>@Constants.ProductName (@Utils.DetermineToolVersion()) is an open source project. For issues or feedback visit the <a href="@Constants.LinkGithubTestTool">AWS Lambda for .NET Core GitHub repository.</a></p>
</footer>
</article>
</main>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,40 @@ main {
}

.sidebar {
background-color: #fafafa;
background-color: #141f2e;
}

.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
display: flex;
align-items: center;
}

.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}

.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}

.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}

@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}

.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}

@media (min-width: 641px) {
Expand Down Expand Up @@ -54,9 +87,9 @@ main {
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
Loading
Loading