Skip to content

Commit

Permalink
Add LaunchProfile with '--launch-profile' and '-lp' (#193)
Browse files Browse the repository at this point in the history
This allows you to select which launch profile to use when aspir8 builds the aspire manifest file, allowing you to handle custom environment builds individually for the same AppHost project.
Implementing this satisfies #189
  • Loading branch information
prom3theu5 authored May 13, 2024
1 parent c18c899 commit 0a7212b
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 8 deletions.
1 change: 1 addition & 0 deletions docs/Writerside/topics/Build-Command.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ The command will first create the manifest file, however, this can be overridden
| --disable-secrets | | `ASPIRATE_DISABLE_SECRETS` | Disables secrets management features. |
| --runtime-identifier | | `ASPIRATE_RUNTIME_IDENTIFIER` | Sets the runtime identifier for project builds. Defaults to `linux-x64`. |
| --compose-build | | | Can be included one or more times to set certain dockerfile resource building to be handled by the compose file. This will skip build and push in aspirate. |
| --launch-profile | -lp | 'ASPIRATE_LAUNCH_PROFILE' | The launch profile to use when building the Aspire Manifest. |
3 changes: 2 additions & 1 deletion docs/Writerside/topics/Generate-Command.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,5 @@ a Helm chart is what's classed as an "Ejected Deployment" and is not managed by
| --private-registry-password | | `ASPIRATE_PRIVATE_REGISTRY_PASSWORD` | The password for the private registry. This is required if passing `--private-registry`. |
| --private-registry-email | | `ASPIRATE_PRIVATE_REGISTRY_EMAIL` | The email for the private registry. This is purely optional and will default to `[email protected]`. |
| --include-dashboard | | `ASPIRATE_INCLUDE_DASHBOARD` | Boolean flag to specify if the Aspire dashboard should also be included in deployments. |
| --compose-build | | | Can be included one or more times to set certain dockerfile resource building to be handled by the compose file. This will skip build and push in aspirate. |
| --compose-build | | | Can be included one or more times to set certain dockerfile resource building to be handled by the compose file. This will skip build and push in aspirate. |
| --launch-profile | -lp | 'ASPIRATE_LAUNCH_PROFILE' | The launch profile to use when building the Aspire Manifest. |
3 changes: 2 additions & 1 deletion docs/Writerside/topics/Run-Command.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ This deletes anything added to the Namespace within the state file, and removes
| --private-registry-password | | `ASPIRATE_PRIVATE_REGISTRY_PASSWORD` | The password for the private registry. This is required if passing `--private-registry`. |
| --private-registry-email | | `ASPIRATE_PRIVATE_REGISTRY_EMAIL` | The email for the private registry. This is purely optional and will default to `[email protected]`. |
| --include-dashboard | | `ASPIRATE_INCLUDE_DASHBOARD` | Boolean flag to specify if the Aspire dashboard should also be included in deployments. |
| --clear-namespace | | `ASPIRATE_ALLOW_CLEAR_NAMESPACE` | Boolean flag to specify the specified namespace should automatically be cleaned during a deployment. |
| --clear-namespace | | `ASPIRATE_ALLOW_CLEAR_NAMESPACE` | Boolean flag to specify the specified namespace should automatically be cleaned during a deployment. |
| --launch-profile | -lp | 'ASPIRATE_LAUNCH_PROFILE' | The launch profile to use when building the Aspire Manifest. |
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ public override async Task<bool> ExecuteAsync()
return true;
}

Logger.MarkupLine("[bold]Generating Aspire Manifest for supplied App Host:[/]");
Logger.MarkupLine("[bold]Generating Aspire Manifest for supplied App Host[/]");

var result = await manifestCompositionService.BuildManifestForProject(CurrentState.ProjectPath);
var result = await manifestCompositionService.BuildManifestForProject(CurrentState.ProjectPath, CurrentState.LaunchProfile);

if (result.Success)
{
Expand Down
1 change: 1 addition & 0 deletions src/Aspirate.Commands/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ protected BaseCommand(string name, string description)
AddOption(NonInteractiveOption.Instance);
AddOption(DisableSecretsOption.Instance);
AddOption(DisableStateOption.Instance);
AddOption(LaunchProfileOption.Instance);
Handler = CommandHandler.Create<TOptions, IServiceCollection>(ConstructCommand);
}

Expand Down
1 change: 1 addition & 0 deletions src/Aspirate.Commands/Commands/BaseCommandOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ public abstract class BaseCommandOptions : ICommandOptions
public bool? DisableSecrets { get; set; }
public bool? DisableState { get; set; }
public string? SecretPassword { get; set; }
public string? LaunchProfile { get; set; }
}
20 changes: 20 additions & 0 deletions src/Aspirate.Commands/Options/LaunchProfileOption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Aspirate.Commands.Options;

public sealed class LaunchProfileOption : BaseOption<string?>
{
private static readonly string[] _aliases =
{
"-lp",
"--launch-profile"
};

private LaunchProfileOption() : base(_aliases, "ASPIRATE_LAUNCH_PROFILE", null)
{
Name = nameof(ICommandOptions.LaunchProfile);
Description = "The launch profile to use when building the aspire manifest from the AppHost.";
Arity = ArgumentArity.ExactlyOne;
IsRequired = false;
}

public static LaunchProfileOption Instance { get; } = new();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ namespace Aspirate.Services.Implementations;

public class AspireManifestCompositionService(IFileSystem fileSystem, IAnsiConsole console, IShellExecutionService shellExecutionService) : IAspireManifestCompositionService
{
public async Task<(bool Success, string FullPath)> BuildManifestForProject(string appHostProject)
public async Task<(bool Success, string FullPath)> BuildManifestForProject(string appHostProject, string? launchProfile)
{
var normalizedPath = fileSystem.NormalizePath(appHostProject);

var argumentsBuilder = ArgumentsBuilder.Create()
.AppendArgument(DotNetSdkLiterals.RunArgument, string.Empty, quoteValue: false)
.AppendArgument(DotNetSdkLiterals.RunArgument, string.Empty, quoteValue: false);

if (!string.IsNullOrEmpty(launchProfile))
{
console.MarkupLine($"[bold]Using Custom Launch Profile: [blue]{launchProfile}[/][/]");

argumentsBuilder
.AppendArgument(DotNetSdkLiterals.LaunchProfileArgument, launchProfile, quoteValue: false);
}

argumentsBuilder
.AppendArgument(DotNetSdkLiterals.ProjectArgument, normalizedPath)
.AppendArgument(DotNetSdkLiterals.ArgumentDelimiter, string.Empty, quoteValue: false)
.AppendArgument(DotNetSdkLiterals.PublisherArgument, AspireLiterals.ManifestPublisherArgument, quoteValue: false)
Expand All @@ -26,9 +36,16 @@ public class AspireManifestCompositionService(IFileSystem fileSystem, IAnsiConso
Command = DotNetSdkLiterals.DotNetCommand,
PreCommandMessage = "Generating Aspire Manifest...",
ArgumentsBuilder = argumentsBuilder,
ShowOutput = true,
ShowOutput = false,
});

if (!string.IsNullOrEmpty(newManifestFile.Error))
{
console.MarkupLine($"[red]Error: {newManifestFile.Error}[/]");
console.MarkupLine($"[red]Could not build the manifest for the supplied details. Exiting rather than building default manifest file.[/]");
ActionCausesExitException.ExitNow();
}

return (newManifestFile.Success, outputFile);
}
}
1 change: 1 addition & 0 deletions src/Aspirate.Shared/Interfaces/Commands/ICommandOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ public interface ICommandOptions
bool? DisableSecrets { get; set; }
bool? DisableState { get; set; }
string? SecretPassword { get; set; }
string? LaunchProfile { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public interface IAspireManifestCompositionService
/// Builds a manifest for the specified application host project.
/// </summary>
/// <param name="appHostProject">The path to the application host project.</param>
/// <param name="launchProfile">The aspire launch profile to use.</param>
/// <returns>A tuple indicating the success status and the full path of the built manifest.</returns>
Task<(bool Success, string FullPath)> BuildManifestForProject(string appHostProject);
Task<(bool Success, string FullPath)> BuildManifestForProject(string appHostProject, string? launchProfile);
}
1 change: 1 addition & 0 deletions src/Aspirate.Shared/Literals/DotNetSdkLiterals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static class DotNetSdkLiterals
public const string OutputPathArgument = "--output-path";
public const string SelfContainedArgument = "--self-contained";
public const string NoLogoArgument = "--nologo";
public const string LaunchProfileArgument = "--launch-profile";
public const string RuntimeIdentifierArgument = "-r";
public const string OsArgument = "--os";
public const string ArchArgument = "--arch";
Expand Down
4 changes: 4 additions & 0 deletions src/Aspirate.Shared/Models/Aspirate/AspirateState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public class AspirateState :
[JsonPropertyName("outputPath")]
public string? OutputPath { get; set; }

[RestorableStateProperty]
[JsonPropertyName("launchProfile")]
public string? LaunchProfile { get; set; }

[RestorableStateProperty]
[JsonPropertyName("allowClearNamespace")]
public bool? AllowClearNamespace { get; set; }
Expand Down

0 comments on commit 0a7212b

Please sign in to comment.