Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public static class SquidStdBootstrapPluginExtensions
/// across the whole set, and invokes <see cref="ISquidStdPlugin.Configure" /> for each plugin
/// in order against the bootstrap container. Must be called before the bootstrap starts, so
/// plugins can register configuration sections before the configuration is loaded. Relative
/// directories are resolved against the bootstrap root directory. Any failure aborts startup:
/// directories are resolved against the bootstrap root directory and created when missing
/// (an empty directory yields no plugins). Any failure aborts startup:
/// loader problems raise <see cref="Exceptions.PluginLoadException" /> and plugin exceptions
/// propagate unchanged. Plugin assemblies load into the default AssemblyLoadContext and are
/// fully trusted: there is no unloading and no version isolation. Note that plugin load
Expand Down Expand Up @@ -56,6 +57,10 @@ Action<PluginCollectionBuilder> configure
? directory
: Path.Combine(bootstrap.Options.RootDirectory, directory);

// Managed like the bootstrap's DirectoriesConfig entries: a missing plugin
// directory is created (and simply yields no plugins), not treated as an error.
Directory.CreateDirectory(resolved);

plugins.AddRange(PluginAssemblyScanner.Scan(resolved));
}

Expand Down
3 changes: 2 additions & 1 deletion src/SquidStd.Plugin/PluginCollectionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public PluginCollectionBuilder Add(ISquidStdPlugin plugin)

/// <summary>
/// Adds a directory to scan for external plugin assemblies (*.dll, non-recursive).
/// Relative paths are resolved against the bootstrap root directory.
/// Relative paths are resolved against the bootstrap root directory; a missing
/// directory is created and yields no plugins.
/// </summary>
/// <param name="path">Absolute or root-relative directory path.</param>
/// <returns>The same builder for chaining.</returns>
Expand Down
2 changes: 2 additions & 0 deletions src/SquidStd.Plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ await bootstrap.RunAsync();
can depend on an internal one and vice versa.
- `Configure` runs before the configuration load, so plugins can register their own configuration
sections and services ahead of time.
- Plugin directories are managed like the other bootstrap directories: a missing directory is
created on the spot and simply yields no plugins.
- Each plugin receives a `PluginContext` populated with the standard keys: `PluginContextKeys.RootDirectory`
(the bootstrap root directory) and `PluginContextKeys.AppName` (the bootstrap app name).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ public async Task UsePlugins_LoadsExternalPluginsFromRelativeDirectory()
Assert.Equal("tests.external", bootstrap.Container.Resolve<string>(serviceKey: "plugin-marker"));
}

[Fact]
public async Task UsePlugins_MissingDirectory_IsCreatedAndYieldsNoPlugins()
{
using var root = new TempDirectory();

await using var bootstrap = SquidStdBootstrap.Create(
new SquidStdOptions { ConfigName = "plugintest", RootDirectory = root.Path }
);

bootstrap.UsePlugins(plugins => plugins.FromDirectory("plugins"));

Assert.True(Directory.Exists(root.Combine("plugins")));
}

[Fact]
public async Task UsePlugins_AfterStart_Throws()
{
Expand Down
Loading