Browse Source

Cli: Create migrations after project generation

pull/12486/head
Yunus Emre Kalkan 4 years ago
parent
commit
98ab3e4291
  1. 100
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs
  2. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  3. 41
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
  4. 43
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/DotnetEfToolManager.cs
  5. 111
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/InitialMigrationCreator.cs

100
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands.Services;
using Volo.Abp.Cli.Utils; using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -12,14 +13,18 @@ namespace Volo.Abp.Cli.Commands;
public class CreateMigrationAndRunMigratorCommand : IConsoleCommand, ITransientDependency public class CreateMigrationAndRunMigratorCommand : IConsoleCommand, ITransientDependency
{ {
private readonly InitialMigrationCreator _ınıtialMigrationCreator;
public const string Name = "create-migration-and-run-migrator"; public const string Name = "create-migration-and-run-migrator";
public ICmdHelper CmdHelper { get; } public ICmdHelper CmdHelper { get; }
public DotnetEfToolManager DotnetEfToolManager { get; }
public ILogger<CreateMigrationAndRunMigratorCommand> Logger { get; set; } public ILogger<CreateMigrationAndRunMigratorCommand> Logger { get; set; }
public CreateMigrationAndRunMigratorCommand(ICmdHelper cmdHelper) public CreateMigrationAndRunMigratorCommand(ICmdHelper cmdHelper, InitialMigrationCreator ınıtialMigrationCreator, DotnetEfToolManager dotnetEfToolManager)
{ {
_ınıtialMigrationCreator = ınıtialMigrationCreator;
CmdHelper = cmdHelper; CmdHelper = cmdHelper;
DotnetEfToolManager = dotnetEfToolManager;
Logger = NullLogger<CreateMigrationAndRunMigratorCommand>.Instance; Logger = NullLogger<CreateMigrationAndRunMigratorCommand>.Instance;
} }
@ -39,110 +44,31 @@ public class CreateMigrationAndRunMigratorCommand : IConsoleCommand, ITransientD
throw new Exception("DbMigrator is not found!"); throw new Exception("DbMigrator is not found!");
} }
if (!IsDotNetEfToolInstalled()) await DotnetEfToolManager.BeSureInstalledAsync();
{
InstallDotnetEfTool();
}
var tenantDbContextName = FindTenantDbContextName(dbMigrationsFolder); var migrationsCreatedSuccessfully = await _ınıtialMigrationCreator.CreateAsync(commandLineArgs.Target, !nolayers);
var dbContextName = tenantDbContextName != null ?
FindDbContextName(dbMigrationsFolder)
: null;
var migrationOutput = AddMigrationAndGetOutput(dbMigrationsFolder, dbContextName, "Migrations"); if (migrationsCreatedSuccessfully)
var tenantMigrationOutput = tenantDbContextName != null ?
AddMigrationAndGetOutput(dbMigrationsFolder, tenantDbContextName, "TenantMigrations")
: null;
if (CheckMigrationOutput(migrationOutput) && CheckMigrationOutput(tenantMigrationOutput))
{ {
if (nolayers) if (nolayers)
{ {
// Migration added successfully CmdHelper.RunCmd("dotnet run --migrate-database", Path.GetDirectoryName(Path.Combine(dbMigrationsFolder, "MyCompanyName.MyProjectName")));
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(Path.Combine(dbMigrationsFolder, "MyCompanyName.MyProjectName")) + "\" && dotnet run --migrate-database");
} }
else else
{ {
// Migration added successfully CmdHelper.RunCmd("dotnet run", Path.GetDirectoryName(dbMigratorProjectPath));
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run");
} }
await Task.CompletedTask; await Task.CompletedTask;
} }
else else
{ {
var exceptionMsg = "Migrations failed! A migration command didn't run successfully:" + var exceptionMsg = "Migrations failed! A migration command didn't run successfully.";
Environment.NewLine +
Environment.NewLine + migrationOutput +
Environment.NewLine +
Environment.NewLine + tenantMigrationOutput;
Logger.LogError(exceptionMsg); Logger.LogError(exceptionMsg);
throw new Exception(exceptionMsg); throw new Exception(exceptionMsg);
} }
} }
private string FindTenantDbContextName(string dbMigrationsFolder)
{
var tenantDbContext = Directory.GetFiles(dbMigrationsFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault() ??
Directory.GetFiles(dbMigrationsFolder, "*TenantDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault();
if (tenantDbContext == null)
{
return null;
}
return Path.GetFileName(tenantDbContext).RemovePostFix(".cs");
}
private string FindDbContextName(string dbMigrationsFolder)
{
var dbContext = Directory.GetFiles(dbMigrationsFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs")) ??
Directory.GetFiles(dbMigrationsFolder, "*DbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault(fp => !fp.EndsWith("TenantDbContext.cs"));
if (dbContext == null)
{
return null;
}
return Path.GetFileName(dbContext).RemovePostFix(".cs");
}
private string AddMigrationAndGetOutput(string dbMigrationsFolder, string dbContext, string outputDirectory)
{
var dbContextOption = string.IsNullOrWhiteSpace(dbContext)
? string.Empty
: $"--context {dbContext}";
var addMigrationCmd = $"cd \"{dbMigrationsFolder}\" && " +
$"dotnet ef migrations add Initial --output-dir {outputDirectory} {dbContextOption}";
return CmdHelper.RunCmdAndGetOutput(addMigrationCmd, out int exitCode);
}
private bool IsDotNetEfToolInstalled()
{
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g", out int exitCode);
return output.Contains("dotnet-ef");
}
private static bool CheckMigrationOutput(string output)
{
return output == null || (output.Contains("Done.") &&
output.Contains("To undo this action") &&
output.Contains("ef migrations remove"));
}
private void InstallDotnetEfTool()
{
Logger.LogInformation("Installing dotnet-ef tool...");
CmdHelper.RunCmd("dotnet tool install --global dotnet-ef");
Logger.LogInformation("dotnet-ef tool is installed.");
}
private static string GetDbMigratorProjectPath(string dbMigrationsFolderPath) private static string GetDbMigratorProjectPath(string dbMigrationsFolderPath)
{ {
var srcFolder = Directory.GetParent(dbMigrationsFolderPath); var srcFolder = Directory.GetParent(dbMigrationsFolderPath);

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -32,8 +32,9 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien
SolutionPackageVersionFinder solutionPackageVersionFinder, SolutionPackageVersionFinder solutionPackageVersionFinder,
ICmdHelper cmdHelper, ICmdHelper cmdHelper,
IInstallLibsService installLibsService, IInstallLibsService installLibsService,
AngularPwaSupportAdder angularPwaSupportAdder) AngularPwaSupportAdder angularPwaSupportAdder,
: base(connectionStringProvider, solutionPackageVersionFinder, cmdHelper, installLibsService, angularPwaSupportAdder) InitialMigrationCreator ınitialMigrationCreator)
: base(connectionStringProvider, solutionPackageVersionFinder, cmdHelper, installLibsService, angularPwaSupportAdder, ınitialMigrationCreator)
{ {
TemplateProjectBuilder = templateProjectBuilder; TemplateProjectBuilder = templateProjectBuilder;
TemplateInfoProvider = templateInfoProvider; TemplateInfoProvider = templateInfoProvider;
@ -79,6 +80,7 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien
Logger.LogInformation($"'{projectName}' has been successfully created to '{projectArgs.OutputFolder}'"); Logger.LogInformation($"'{projectName}' has been successfully created to '{projectArgs.OutputFolder}'");
RunGraphBuildForMicroserviceServiceTemplate(projectArgs); RunGraphBuildForMicroserviceServiceTemplate(projectArgs);
await CreateInitialMigrationsAsync(projectArgs);
await RunInstallLibsForWebTemplateAsync(projectArgs); await RunInstallLibsForWebTemplateAsync(projectArgs);
ConfigurePwaSupportForAngular(projectArgs); ConfigurePwaSupportForAngular(projectArgs);

41
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs

@ -6,6 +6,7 @@ using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using NUglify.Helpers;
using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.ProjectModification;
using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.Commands.Services;
@ -26,6 +27,7 @@ public abstract class ProjectCreationCommandBase
public ICmdHelper CmdHelper { get; } public ICmdHelper CmdHelper { get; }
public IInstallLibsService InstallLibsService { get; } public IInstallLibsService InstallLibsService { get; }
public AngularPwaSupportAdder AngularPwaSupportAdder { get; } public AngularPwaSupportAdder AngularPwaSupportAdder { get; }
public InitialMigrationCreator InitialMigrationCreator { get; }
public ILogger<NewCommand> Logger { get; set; } public ILogger<NewCommand> Logger { get; set; }
public ProjectCreationCommandBase( public ProjectCreationCommandBase(
@ -33,13 +35,15 @@ public abstract class ProjectCreationCommandBase
SolutionPackageVersionFinder solutionPackageVersionFinder, SolutionPackageVersionFinder solutionPackageVersionFinder,
ICmdHelper cmdHelper, ICmdHelper cmdHelper,
IInstallLibsService installLibsService, IInstallLibsService installLibsService,
AngularPwaSupportAdder angularPwaSupportAdder) AngularPwaSupportAdder angularPwaSupportAdder,
InitialMigrationCreator ınitialMigrationCreator)
{ {
ConnectionStringProvider = connectionStringProvider; ConnectionStringProvider = connectionStringProvider;
SolutionPackageVersionFinder = solutionPackageVersionFinder; SolutionPackageVersionFinder = solutionPackageVersionFinder;
CmdHelper = cmdHelper; CmdHelper = cmdHelper;
InstallLibsService = installLibsService; InstallLibsService = installLibsService;
AngularPwaSupportAdder = angularPwaSupportAdder; AngularPwaSupportAdder = angularPwaSupportAdder;
InitialMigrationCreator = ınitialMigrationCreator;
Logger = NullLogger<NewCommand>.Instance; Logger = NullLogger<NewCommand>.Instance;
} }
@ -337,6 +341,41 @@ public abstract class ProjectCreationCommandBase
} }
} }
protected async Task CreateInitialMigrationsAsync(ProjectBuildArgs projectArgs)
{
if (projectArgs.DatabaseProvider == DatabaseProvider.MongoDb)
{
return;
}
var efCoreProjectPath = string.Empty;
bool isLayeredTemplate;
switch (projectArgs.TemplateName)
{
case AppTemplate.TemplateName:
case AppProTemplate.TemplateName:
efCoreProjectPath = Directory.GetFiles(projectArgs.OutputFolder, "*EntityFrameworkCore.csproj", SearchOption.AllDirectories).FirstOrDefault();
isLayeredTemplate = true;
break;
case AppNoLayersTemplate.TemplateName:
case AppNoLayersProTemplate.TemplateName:
efCoreProjectPath = Directory.GetFiles(projectArgs.OutputFolder, "*.csproj", SearchOption.AllDirectories).FirstOrDefault();
isLayeredTemplate = false;
break;
default:
return;
}
if (string.IsNullOrWhiteSpace(efCoreProjectPath))
{
Logger.LogWarning("Couldn't find EntityFrameworkCore project to create initial migrations!");
return;
}
await InitialMigrationCreator.CreateAsync(Path.GetDirectoryName(efCoreProjectPath), isLayeredTemplate);
}
protected void ConfigurePwaSupportForAngular(ProjectBuildArgs projectArgs) protected void ConfigurePwaSupportForAngular(ProjectBuildArgs projectArgs)
{ {
var isAngular = projectArgs.UiFramework == UiFramework.Angular; var isAngular = projectArgs.UiFramework == UiFramework.Angular;

43
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/DotnetEfToolManager.cs

@ -0,0 +1,43 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands.Services;
public class DotnetEfToolManager : ISingletonDependency
{
public ICmdHelper CmdHelper { get; }
public ILogger<DotnetEfToolManager> Logger { get; set; }
public DotnetEfToolManager(ICmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
Logger = NullLogger<DotnetEfToolManager>.Instance;
}
public async Task BeSureInstalledAsync()
{
if (IsDotNetEfToolInstalled())
{
return;
}
InstallDotnetEfTool();
}
private bool IsDotNetEfToolInstalled()
{
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g");
return output.Contains("dotnet-ef");
}
private void InstallDotnetEfTool()
{
Logger.LogInformation("Installing dotnet-ef tool...");
CmdHelper.RunCmd("dotnet tool install --global dotnet-ef");
Logger.LogInformation("dotnet-ef tool is installed.");
}
}

111
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/InitialMigrationCreator.cs

@ -0,0 +1,111 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands.Services;
public class InitialMigrationCreator : ITransientDependency
{
public ICmdHelper CmdHelper { get; }
public DotnetEfToolManager DotnetEfToolManager { get; }
public ILogger<InitialMigrationCreator> Logger { get; set; }
public InitialMigrationCreator(ICmdHelper cmdHelper, DotnetEfToolManager dotnetEfToolManager)
{
CmdHelper = cmdHelper;
DotnetEfToolManager = dotnetEfToolManager;
Logger = NullLogger<InitialMigrationCreator>.Instance;
}
public async Task<bool> CreateAsync(string targetProjectFolder, bool layeredTemplate = true)
{
if (targetProjectFolder == null || !Directory.Exists(targetProjectFolder))
{
Logger.LogError($"This path doesn't exist: {targetProjectFolder}");
return false;
}
Logger.LogInformation("Creating initial migrations...");
await DotnetEfToolManager.BeSureInstalledAsync();
var tenantDbContextName = FindTenantDbContextName(targetProjectFolder);
var dbContextName = tenantDbContextName != null ?
FindDbContextName(targetProjectFolder)
: null;
var migrationOutput = AddMigrationAndGetOutput(targetProjectFolder, dbContextName, "Migrations");
var tenantMigrationOutput = tenantDbContextName != null ?
AddMigrationAndGetOutput(targetProjectFolder, tenantDbContextName, "TenantMigrations")
: null;
var migrationSuccess = CheckMigrationOutput(migrationOutput) && CheckMigrationOutput(tenantMigrationOutput);
if (migrationSuccess)
{
Logger.LogInformation("Initial migrations are created.");
}
else
{
Logger.LogError("Creating initial migrations process is failed! Details:" + Environment.NewLine
+ migrationOutput + Environment.NewLine
+ tenantMigrationOutput + Environment.NewLine);
}
return migrationSuccess;
}
private string FindTenantDbContextName(string projectFolder)
{
var tenantDbContext = Directory.GetFiles(projectFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault() ??
Directory.GetFiles(projectFolder, "*TenantDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault();
if (tenantDbContext == null)
{
return null;
}
return Path.GetFileName(tenantDbContext).RemovePostFix(".cs");
}
private string FindDbContextName(string projectFolder)
{
var dbContext = Directory.GetFiles(projectFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs")) ??
Directory.GetFiles(projectFolder, "*DbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault(fp => !fp.EndsWith("TenantDbContext.cs"));
if (dbContext == null)
{
return null;
}
return Path.GetFileName(dbContext).RemovePostFix(".cs");
}
private string AddMigrationAndGetOutput(string dbMigrationsFolder, string dbContext, string outputDirectory)
{
var dbContextOption = string.IsNullOrWhiteSpace(dbContext)
? string.Empty
: $"--context {dbContext}";
var addMigrationCmd = $"dotnet ef migrations add Initial --output-dir {outputDirectory} {dbContextOption}";
return CmdHelper.RunCmdAndGetOutput(addMigrationCmd, out int exitCode, dbMigrationsFolder);
}
private static bool CheckMigrationOutput(string output)
{
return output == null || (output.Contains("Done.") &&
output.Contains("To undo this action") &&
output.Contains("ef migrations remove"));
}
}
Loading…
Cancel
Save