Skip to content

Commit

Permalink
add db only install, add support for wizard args, add 4.1.0 migration
Browse files Browse the repository at this point in the history
  • Loading branch information
kentico-ericd committed Sep 25, 2024
1 parent a031137 commit 7d51817
Show file tree
Hide file tree
Showing 26 changed files with 302 additions and 145 deletions.
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"args": ["i"],
"cwd": "${workspaceFolder}",
"console": "externalTerminal",
"stopAtEntry": false
"stopAtEntry": false,
"brokeredServicePipeName": "undefined",
}
]
}
2 changes: 1 addition & 1 deletion src/Commands/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class BuildCommand : AbstractCommand
public override IEnumerable<string> Keywords => ["b", "build"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [];


public override string Description => "Builds a project";
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/CodeGenerateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class CodeGenerateCommand : AbstractCommand
public override IEnumerable<string> Keywords => ["g", "generate"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [];


public override string Description => "Generates code files for Xperience objects";
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/DeleteCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class DeleteCommand : AbstractCommand
public override IEnumerable<string> Keywords => ["d", "delete"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [];


public override string Description => "Deletes a project and its database";
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/HelpCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class HelpCommand : AbstractCommand
public override IEnumerable<string> Keywords => ["?", "help"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [];


public override string Description => "Displays the help menu (this screen)";
Expand Down
110 changes: 88 additions & 22 deletions src/Commands/InstallCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Diagnostics;

using Xperience.Manager.Configuration;
using Xperience.Manager.Helpers;
using Xperience.Manager.Options;
using Xperience.Manager.Services;
using Xperience.Manager.Wizards;
Expand All @@ -14,17 +15,19 @@ namespace Xperience.Manager.Commands
/// </summary>
public class InstallCommand : AbstractCommand
{
private const string DATABASE = "db";
private readonly ToolProfile newInstallationProfile = new();
private readonly IShellRunner shellRunner;
private readonly IConfigManager configManager;
private readonly IScriptBuilder scriptBuilder;
private readonly IWizard<InstallOptions> wizard;
private readonly IWizard<InstallProjectOptions> projectWizard;
private readonly IWizard<InstallDatabaseOptions> dbWizard;


public override IEnumerable<string> Keywords => ["i", "install"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [DATABASE];


public override string Description => "Installs a new XbK instance";
Expand All @@ -41,9 +44,15 @@ internal InstallCommand()
}


public InstallCommand(IShellRunner shellRunner, IScriptBuilder scriptBuilder, IWizard<InstallOptions> wizard, IConfigManager configManager)
public InstallCommand(
IShellRunner shellRunner,
IScriptBuilder scriptBuilder,
IWizard<InstallProjectOptions> projectWizard,
IWizard<InstallDatabaseOptions> dbWizard,
IConfigManager configManager)
{
this.wizard = wizard;
this.dbWizard = dbWizard;
this.projectWizard = projectWizard;
this.shellRunner = shellRunner;
this.configManager = configManager;
this.scriptBuilder = scriptBuilder;
Expand All @@ -57,22 +66,39 @@ public override async Task Execute(ToolProfile? profile, string? action)
return;
}

// Override default values of InstallOptions with values from config file
wizard.Options = await configManager.GetDefaultInstallOptions();
var options = await wizard.Run();
AnsiConsole.WriteLine();
// Override default values of InstallDatabaseOptions and InstallProjectOptions with values from config file
dbWizard.Options = await configManager.GetDefaultInstallDatabaseOptions();
projectWizard.Options = await configManager.GetDefaultInstallProjectOptions();

// Only install database if "db" argument is passed
InstallDatabaseOptions? dbOptions = null;
if (!string.IsNullOrEmpty(action) && action.Equals(DATABASE))
{
dbOptions = await dbWizard.Run(InstallDatabaseWizard.SKIP_EXISTINGDB_STEP);
await InstallDatabaseTool();
await CreateDatabase(dbOptions, true);

return;
}

var projectOptions = await projectWizard.Run();
if (!IsAdminTemplate(projectOptions))
{
dbOptions = await dbWizard.Run();
}

newInstallationProfile.ProjectName = options.ProjectName;
newInstallationProfile.WorkingDirectory = $"{options.InstallRootPath}\\{options.ProjectName}";
newInstallationProfile.ProjectName = projectOptions.ProjectName;
newInstallationProfile.WorkingDirectory = $"{projectOptions.InstallRootPath}\\{projectOptions.ProjectName}";

AnsiConsole.WriteLine();
await CreateWorkingDirectory();
await InstallTemplate(options);
await CreateProjectFiles(options);
await InstallTemplate(projectOptions);
await CreateProjectFiles(projectOptions);

// Admin boilerplate project doesn't require database install or profile
if (!IsAdminTemplate(options))
if (!IsAdminTemplate(projectOptions) && dbOptions is not null)
{
await CreateDatabase(options);
await CreateDatabase(dbOptions, false);
await configManager.AddProfile(newInstallationProfile);

// Select new profile
Expand Down Expand Up @@ -113,7 +139,7 @@ private async Task CreateWorkingDirectory()
}


private async Task CreateDatabase(InstallOptions options)
private async Task CreateDatabase(InstallDatabaseOptions options, bool isDatabaseOnly)
{
if (StopProcessing)
{
Expand All @@ -125,6 +151,12 @@ private async Task CreateDatabase(InstallOptions options)
string databaseScript = scriptBuilder.SetScript(ScriptType.DatabaseInstall)
.WithPlaceholders(options)
.Build();
// Database-only install requires removal of "dotnet" from the script to run global tool
if (isDatabaseOnly)
{
databaseScript = databaseScript.Replace("dotnet", "");
}

await shellRunner.Execute(new(databaseScript)
{
ErrorHandler = ErrorDataReceived,
Expand All @@ -133,7 +165,7 @@ await shellRunner.Execute(new(databaseScript)
}


private async Task CreateProjectFiles(InstallOptions options)
private async Task CreateProjectFiles(InstallProjectOptions options)
{
if (StopProcessing)
{
Expand Down Expand Up @@ -167,8 +199,43 @@ await shellRunner.Execute(new(installScript)
}).WaitForExitAsync();
}

private async Task InstallDatabaseTool()
{
if (StopProcessing)
{
return;
}

// Get desired database tool version
var versions = await NuGetVersionHelper.GetPackageVersions(Constants.DATABASE_TOOL);
var filtered = versions.Where(v => !v.IsPrerelease && !v.IsLegacyVersion && v.Major >= 25)
.Select(v => v.Version)
.OrderByDescending(v => v);
var toolVersion = AnsiConsole.Prompt(new SelectionPrompt<Version>()
.Title($"Which [{Constants.PROMPT_COLOR}]version[/]?")
.PageSize(10)
.UseConverter(v => $"{v.Major}.{v.Minor}.{v.Build}")
.MoreChoicesText("Scroll for more...")
.AddChoices(filtered));

AnsiConsole.WriteLine();
AnsiConsole.MarkupLineInterpolated($"[{Constants.EMPHASIS_COLOR}]Uninstalling previous database tool...[/]");

string uninstallScript = scriptBuilder.SetScript(ScriptType.UninstallDatabaseTool).Build();
// Don't use base error handler for uninstall script as it throws when no tool is installed
// Just skip uninstall step in case of error and try to continue
await shellRunner.Execute(new(uninstallScript)).WaitForExitAsync();

AnsiConsole.MarkupLineInterpolated($"[{Constants.EMPHASIS_COLOR}]Installing database tool version {toolVersion}...[/]");

string installScript = scriptBuilder.SetScript(ScriptType.InstallDatabaseTool)
.AppendVersion(toolVersion)
.Build();
await shellRunner.Execute(new(installScript) { ErrorHandler = ErrorDataReceived }).WaitForExitAsync();
}


private async Task InstallTemplate(InstallOptions options)
private async Task InstallTemplate(InstallProjectOptions options)
{
if (StopProcessing)
{
Expand All @@ -180,20 +247,19 @@ private async Task InstallTemplate(InstallOptions options)
string uninstallScript = scriptBuilder.SetScript(ScriptType.TemplateUninstall).Build();
// Don't use base error handler for uninstall script as it throws when no templates are installed
// Just skip uninstall step in case of error and try to continue
var uninstallCmd = shellRunner.Execute(new(uninstallScript));
await uninstallCmd.WaitForExitAsync();
await shellRunner.Execute(new(uninstallScript)).WaitForExitAsync();

AnsiConsole.MarkupLineInterpolated($"[{Constants.EMPHASIS_COLOR}]Installing template version {options.Version}...[/]");

string installScript = scriptBuilder.SetScript(ScriptType.TemplateInstall)
.WithPlaceholders(options)
.AppendVersion(options.Version)
.Build();
var installCmd = shellRunner.Execute(new(installScript) { ErrorHandler = ErrorDataReceived });
await installCmd.WaitForExitAsync();
await shellRunner.Execute(new(installScript) { ErrorHandler = ErrorDataReceived }).WaitForExitAsync();
}


private bool IsAdminTemplate(InstallOptions options) => options?.Template.Equals(Constants.TEMPLATE_ADMIN, StringComparison.OrdinalIgnoreCase) ?? false;
private static bool IsAdminTemplate(InstallProjectOptions options) =>
options?.Template.Equals(Constants.TEMPLATE_ADMIN, StringComparison.OrdinalIgnoreCase) ?? false;
}
}
2 changes: 1 addition & 1 deletion src/Commands/MacroCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class MacroCommand : AbstractCommand
public override IEnumerable<string> Keywords => ["m", "macros"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [];


public override string Description => "Re-signs macro signatures";
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/SettingsCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class SettingsCommand : AbstractCommand
public override IEnumerable<string> Keywords => ["s", "settings"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [];


public override string Description => "Configures the appsettings.json of a project";
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class UpdateCommand : AbstractCommand
public override IEnumerable<string> Keywords => ["u", "update"];


public override IEnumerable<string> Parameters => Enumerable.Empty<string>();
public override IEnumerable<string> Parameters => [];


public override string Description => "Updates a project's NuGet packages and database version";
Expand Down
10 changes: 8 additions & 2 deletions src/Configuration/ToolConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,15 @@ public class ToolConfiguration


/// <summary>
/// The <see cref="InstallOptions"/> stored in the configuration file.
/// The <see cref="InstallProjectOptions"/> stored in the configuration file.
/// </summary>
public InstallOptions? DefaultInstallOptions { get; set; }
public InstallProjectOptions? DefaultInstallProjectOptions { get; set; }


/// <summary>
/// The <see cref="InstallDatabaseOptions"/> stored in the configuration file.
/// </summary>
public InstallDatabaseOptions? DefaultInstallDatabaseOptions { get; set; }


/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static class Constants
public const string EMPHASIS_COLOR = "deepskyblue3_1";
public const string PROMPT_COLOR = "lightgoldenrod2_2";

public const string DATABASE_TOOL = "Kentico.Xperience.DbManager";
public const string TEMPLATES_PACKAGE = "kentico.xperience.templates";
public const string TEMPLATE_SAMPLE = "kentico-xperience-sample-mvc";
public const string TEMPLATE_BLANK = "kentico-xperience-mvc";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,10 @@
namespace Xperience.Manager.Options
{
/// <summary>
/// The options used to install Xperience by Kentico project files and databases, used by <see cref="InstallCommand"/>.
/// The options used to install Xperience by Kentico databases, used by <see cref="InstallCommand"/>.
/// </summary>
public class InstallOptions : IWizardOptions
public class InstallDatabaseOptions : IWizardOptions
{
/// <summary>
/// The version of the Xperience by Kentico templates and database to install.
/// </summary>
public Version? Version { get; set; }


/// <summary>
/// The name of the template to install.
/// </summary>
public string Template { get; set; } = "kentico-xperience-sample-mvc";


/// <summary>
/// The name of the Xperience by Kentico project.
/// </summary>
public string ProjectName { get; set; } = "xbk";


/// <summary>
/// The absolute path of the parent directory to install the project within. E.g. if set to
/// "C:\inetpub\wwwroot" a new installation will be created in "C:\inetpub\wwwroot\projectname."
/// </summary>
public string InstallRootPath { get; set; } = Environment.CurrentDirectory;


/// <summary>
/// If <c>true</c>, the "--cloud" parameter is used during installation.
/// </summary>
public bool UseCloud { get; set; } = false;


/// <summary>
/// The name of the new database.
/// </summary>
Expand Down
40 changes: 40 additions & 0 deletions src/Options/InstallProjectOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Xperience.Manager.Commands;

namespace Xperience.Manager.Options
{
/// <summary>
/// The options used to install Xperience by Kentico project files, used by <see cref="InstallCommand"/>.
/// </summary>
public class InstallProjectOptions : IWizardOptions
{
/// <summary>
/// The version of the Xperience by Kentico templates and database to install.
/// </summary>
public Version? Version { get; set; }


/// <summary>
/// The name of the template to install.
/// </summary>
public string Template { get; set; } = "kentico-xperience-sample-mvc";


/// <summary>
/// The name of the Xperience by Kentico project.
/// </summary>
public string ProjectName { get; set; } = "xbk";


/// <summary>
/// The absolute path of the parent directory to install the project within. E.g. if set to
/// "C:\inetpub\wwwroot" a new installation will be created in "C:\inetpub\wwwroot\projectname."
/// </summary>
public string InstallRootPath { get; set; } = Environment.CurrentDirectory;


/// <summary>
/// If <c>true</c>, the "--cloud" parameter is used during installation.
/// </summary>
public bool UseCloud { get; set; } = false;
}
}
Loading

0 comments on commit 7d51817

Please sign in to comment.