feat(cli): add ms microservice template support

1. 新增`ms`微服务模板,包含共享项目、微服务、网关、应用等完整架构
2. 为`hua new`命令添加`ms`模板选项并更新文档
3. 将模板文件嵌入CLI项目输出目录
4. 实现微服务模板的项目构建逻辑,自动安装并使用dotnet自定义模板创建项目
This commit is contained in:
ShaoHua
2026-07-15 11:30:43 +08:00
parent e639ade569
commit 2a6f5f81b7
60 changed files with 1259 additions and 2 deletions
+4
View File
@@ -20,4 +20,8 @@
<PackageReference Include="Volo.Abp.Json" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<Content Include="..\..\templates\ms\**\*" CopyToOutputDirectory="PreserveNewest" LinkBase="templates\ms\" />
</ItemGroup>
</Project>
@@ -114,6 +114,7 @@ public class NewCommand : IConsoleCommand, ITransientDependency
Options:
-t|--template <template-name> (default: app)
Available: app, ms
-v|--version <version> Semantic version number
-o|--output <output-directory> Output directory
-db|--database-provider <provider> Database provider (ef)
@@ -127,6 +128,7 @@ Examples:
hua new MyProject
hua new MyProject -t app -db ef -u mvc
hua new MyProject -t ms
hua new MyProject -o D:\Projects";
}
@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectBuilding.Templates.App;
using Volo.Abp.Cli.ProjectBuilding.Templates.Ms;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectBuilding;
@@ -11,6 +12,7 @@ public class TemplateInfoProvider : ITemplateInfoProvider, ITransientDependency
TemplateInfo? template = name switch
{
"app" => new AppTemplate(),
"ms" => new MicroserviceTemplate(),
_ => null
};
@@ -1,6 +1,9 @@
using System;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectBuilding;
@@ -9,13 +12,16 @@ public class TemplateProjectBuilder : ITransientDependency
{
protected ISourceCodeStore SourceCodeStore { get; }
protected TemplateProjectBuildPipelineBuilder PipelineBuilder { get; }
protected ICmdHelper CmdHelper { get; }
public TemplateProjectBuilder(
ISourceCodeStore sourceCodeStore,
TemplateProjectBuildPipelineBuilder pipelineBuilder)
TemplateProjectBuildPipelineBuilder pipelineBuilder,
ICmdHelper cmdHelper)
{
SourceCodeStore = sourceCodeStore;
PipelineBuilder = pipelineBuilder;
CmdHelper = cmdHelper;
}
public async Task BuildAsync(ProjectBuildArgs args)
@@ -25,6 +31,12 @@ public class TemplateProjectBuilder : ITransientDependency
return;
}
if (args.Template.Name == "ms")
{
await BuildMicroserviceAsync(args);
return;
}
var templatePath = await SourceCodeStore.GetAsync(
args.Template.Name, args.Version);
@@ -43,4 +55,75 @@ public class TemplateProjectBuilder : ITransientDependency
var pipeline = PipelineBuilder.Build(context);
await pipeline.ExecuteAsync();
}
private async Task BuildMicroserviceAsync(ProjectBuildArgs args)
{
var templateDir = ResolveTemplateDirectory();
if (!Directory.Exists(templateDir))
{
throw new FileNotFoundException(
$"Microservice template not found at: {templateDir}. " +
"Ensure the 'templates/ms' directory exists alongside the tool.");
}
// Install the template
var installResult = await CmdHelper.RunAsync($"dotnet new install \"{templateDir}\"");
if (!installResult.IsSuccess)
{
throw new InvalidOperationException(
$"Failed to install microservice template: {installResult.Error}");
}
try
{
// Run dotnet new with the template
var outputDir = args.OutputDirectory;
var projectName = args.ProjectName;
var newResult = await CmdHelper.RunAsync(
$"dotnet new hua-ms -n \"{projectName}\" -o \"{outputDir}\"");
if (!newResult.IsSuccess)
{
throw new InvalidOperationException(
$"Failed to create project: {newResult.Error}");
}
}
finally
{
// Uninstall the template to clean up
await CmdHelper.RunAsync($"dotnet new uninstall \"{templateDir}\"");
}
}
private static string ResolveTemplateDirectory()
{
var assemblyDir = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location) ?? ".";
// First, check relative to the assembly directory (works for published output
// where templates/ms is copied alongside the assembly via CopyToOutputDirectory)
var assemblyRelativePath = Path.Combine(assemblyDir, "templates", "ms");
if (Directory.Exists(assemblyRelativePath))
{
return assemblyRelativePath;
}
// Fall back to upward traversal (works in development when templates/ms
// lives in the repository root above bin/Debug/net9.0)
var directory = new DirectoryInfo(assemblyDir);
while (directory != null)
{
var templatePath = Path.Combine(directory.FullName, "templates", "ms");
if (Directory.Exists(templatePath))
{
return templatePath;
}
directory = directory.Parent;
}
return assemblyRelativePath;
}
}
@@ -0,0 +1,11 @@
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Ms;
public class MicroserviceTemplate : TemplateInfo
{
public MicroserviceTemplate()
: base("ms",
"Microservice solution (gateways + microservices + applications + shared)",
null)
{
}
}