diff --git a/.gitignore b/.gitignore
index e4a167e..39b78d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -400,6 +400,10 @@ FodyWeavers.xsd
*.sln.iml
# End of https://www.toptal.com/developers/gitignore/api/csharp
+
.DS_Store
.vscode
.idea
+
+plugins/*
+!plugins/.gitkeep
\ No newline at end of file
diff --git a/Automancer.csproj b/Automancer.csproj
index f4d5391..f42b80d 100644
--- a/Automancer.csproj
+++ b/Automancer.csproj
@@ -7,7 +7,11 @@
enable
+
+
+
+
diff --git a/Commands/Container/Module.cs b/Commands/Container/Module.cs
index 5599757..5155dd9 100644
--- a/Commands/Container/Module.cs
+++ b/Commands/Container/Module.cs
@@ -4,21 +4,16 @@ using Spectre.Console.Cli;
namespace Automancer.Command.Container;
-public class Module : ICommandModuleWithRegistry
+public class Module : ICommandModule
{
- public void Configure(IConfigurator config)
- {
- // No implementation needed here
- }
-
+ public string Name => "container";
+ public string Description => "Container operations";
public void Configure(IConfigurator config, CommandRegistry registry)
{
- config.AddBranch("container", container =>
+ config.AddBranch(Name, container =>
{
- var description = "Container operations";
-
- container.SetDescription(description);
- registry.Add("container", description);
+ container.SetDescription(Description);
+ registry.Add(Name, Description);
container.AddCommand("ps").WithDescription("List containers");
});
diff --git a/Commands/Image/Module.cs b/Commands/Image/Module.cs
index 111d209..2722d8c 100644
--- a/Commands/Image/Module.cs
+++ b/Commands/Image/Module.cs
@@ -3,18 +3,15 @@ using Spectre.Console.Cli;
namespace Automancer.Command.Image;
-public class Module : ICommandModuleWithRegistry
+public class Module : ICommandModule
{
- public void Configure(IConfigurator config)
- {
- // No implementation needed here
- }
+ public string Name => "image";
+ public string Description => "Docker/podman image operations";
public void Configure(IConfigurator config, CommandRegistry registry)
{
- config.AddBranch("image", image => {
- var description = "Docker/podman image operations";
- image.SetDescription(description);
- registry.Add("image", description);
+ config.AddBranch(Name, image => {
+ image.SetDescription(Description);
+ registry.Add(Name, Description);
image.AddCommand("build").WithDescription("Build a docker image");
image.AddCommand("push").WithDescription("Push a docker image");
diff --git a/Common/CommandRegistry.cs b/Common/CommandRegistry.cs
deleted file mode 100644
index 3c4a611..0000000
--- a/Common/CommandRegistry.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Automancer.Common;
-
-public record CommandInfo(string Path, string? Description);
-
-public class CommandRegistry
-{
- public List Commands { get; } = new();
-
- public void Add(string path, string? description)
- {
- Commands.Add(new CommandInfo(path, description));
- }
-}
diff --git a/Common/ICommandModule.cs b/Common/ICommandModule.cs
deleted file mode 100644
index 1fadae4..0000000
--- a/Common/ICommandModule.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Automancer.Common;
-
-using Spectre.Console.Cli;
-
-public interface ICommandModule
-{
-
- void Configure(IConfigurator config);
-
-}
-
-public interface ICommandModuleWithRegistry : ICommandModule
-{
- void Configure(IConfigurator config, CommandRegistry registry);
-}
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
index bca5197..eff5883 100644
--- a/Program.cs
+++ b/Program.cs
@@ -9,10 +9,10 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Spectre.Console.Cli;
-using Spectre.Console;
-using System.Diagnostics.CodeAnalysis;
+
using Automancer.Commands;
+using System.Reflection;
public abstract class Program
{
@@ -41,6 +41,7 @@ public abstract class Program
var registry = new CommandRegistry();
services.AddSingleton(registry);
+ LoadPluginAssemblies("plugins");
RegisterCommandModules(services);
var registrar = new TypeRegistrar(services);
@@ -58,15 +59,9 @@ public abstract class Program
foreach (var module in modules)
{
- if (module is ICommandModuleWithRegistry withRegistry)
- {
- withRegistry.Configure(config, registry);
- }
- else
- {
- module.Configure(config);
- }
+ module.Configure(config, registry);
}
+
});
})
.Build();
@@ -76,14 +71,17 @@ public abstract class Program
private static void RegisterCommandModules(IServiceCollection services)
{
+
var moduleType = typeof(ICommandModule);
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
-
+
var moduleTypes = assemblies
.SelectMany(a =>
{
try { return a.GetTypes(); }
- catch { return []; }
+ catch {
+ return [];
+ }
})
.Where(t => moduleType.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract)
.ToList();
@@ -94,4 +92,24 @@ public abstract class Program
services.AddSingleton(typeof(ICommandModule), type);
}
}
+
+ private static void LoadPluginAssemblies(string pluginDirectory)
+ {
+ if (!Directory.Exists(pluginDirectory))
+ return;
+
+ var dlls = Directory.GetFiles(pluginDirectory, "*.dll", SearchOption.AllDirectories);
+
+ foreach (var dll in dlls)
+ {
+ try
+ {
+ var asm = Assembly.LoadFrom(dll);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[WARN] Failed to load plugin '{dll}': {ex.Message}");
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/plugins/.gitkeep b/plugins/.gitkeep
new file mode 100644
index 0000000..e69de29