Files
git.stella-ops.org/docs/10_PLUGIN_SDK_GUIDE.md

6.2 KiB
Raw Blame History

#10 · Plugin SDK Guide — StellaOps (v1.5 — 11Jul2025 · template install, no reload, IoC)


##0Audience & Scope
Guidance for developers who extend StellaOps with schedule jobs, scanner adapters, TLS providers, notification channels, etc. Everything here is OSS; commercial variants simply ship additional signed plugins.


##1Prerequisites

Tool Min Version
.NET SDK 9.0.200
StellaOps templates install once via bash dotnet new install StellaOps.Templates::*
Cosign 2.3+ — used to sign DLLs
xUnit 2.6
Docker CLI only if your plugin shells out to containers

##2Repository & Build Output

Every plugin is hosted in git.stellaops.org.
At publish time it must copy its signed artefacts to:

src/backend/Stella.Ops.Plugin.Binaries/<MyPlugin>/
        ├── MyPlugin.dll
        └── MyPlugin.dll.sig

The backend scans this folder on startup, verifies the Cosign signature, confirms the [StellaPluginVersion] gate, then loads the DLL inside an isolated AssemblyLoadContext to avoid dependency clashes


##3Project Scaffold

Generate with the installed template:

dotnet new stellaops-plugin-schedule \
       -n MyPlugin.Schedule \
       --output src

Result:

src/
 ├─ MyPlugin.Schedule/
 │    ├─ MyJob.cs
 │    └─ MyPlugin.Schedule.csproj
 └─ tests/
      └─ MyPlugin.Schedule.Tests/

##4MSBuild Wiring

Add this to MyPlugin.Schedule.csproj so the signed DLL + .sig land in the canonical plugin folder:

<PropertyGroup>
  <StellaPluginOut>$(SolutionDir)src/backend/Stella.Ops.Plugin.Binaries/$(MSBuildProjectName)</StellaPluginOut>
</PropertyGroup>

<ItemGroup>
  
  <ProjectReference Include="..\..\StellaOps.Common\StellaOps.Common.csproj"
                    PrivateAssets="all" /> 
</ItemGroup>

<Target Name="CopyStellaPlugin" AfterTargets="Publish">
  <MakeDir Directories="$(StellaPluginOut)" />
  <Copy SourceFiles="$(PublishDir)$(AssemblyName).dll;$(PublishDir)$(AssemblyName).dll.sig"
        DestinationFolder="$(StellaPluginOut)" />
</Target>

##5DependencyInjection Entrypoint

Backend autodiscovers the static method below:

namespace StellaOps.DependencyInjection;

public static class IoCConfigurator
{
    public static IServiceCollection Configure(this IServiceCollection services,
                                               IConfiguration cfg)
    {
        services.AddSingleton<IJob, MyJob>();        // schedule job
        services.Configure<MyPluginOptions>(cfg.GetSection("Plugins:MyPlugin"));
        return services;
    }
}

##6Schedule Plugins

###6.1 Minimal Job

using StellaOps.Scheduling;             // contract

[StellaPluginVersion("2.0.0")]
public sealed class MyJob : IJob
{
    public async Task ExecuteAsync(CancellationToken ct)
    {
        Console.WriteLine("Hello from plugin!");
        await Task.Delay(500, ct);
    }
}

###6.2 Cron Registration

services.AddCronJob<MyJob>("0 15 * * *"); // everyday 

15:00 Cron syntax follows Hangfire rules 

##7Scanner Adapters

Implement IScannerRunner. Register inside Configure:

services.AddScanner<MyAltScanner>("alt"); // backend 

selects by --engine alt If the engine needs a sidecar container, include a Dockerfile in your repo and document resource expectations. ##8Packaging & Signing

dotnet publish -c Release -p:PublishSingleFile=true -o out
cosign sign --key $COSIGN_KEY out/MyPlugin.Schedule.dll   # sign binary only
sha256sum out/MyPlugin.Schedule.dll > out/.sha256          # optional checksum
zip MyPlugin.zip out/* README.md

Unsigned DLLs are refused when StellaOps:Security:DisableUnsigned=false.

##9Deployment

docker cp MyPlugin.zip <backend>:/opt/plugins/ && docker restart <backend>

Check /health "plugins":["MyPlugin.Schedule@2.0.0"]. (Hotreload was removed to keep the core process simple and memorysafe.)

##10Configuration Patterns

Need Pattern
Settings Plugins:MyPlugin:* in appsettings.json.
Secrets Redis secure:: (encrypted per TLS provider).
Dynamic cron Implement ICronConfigurable; UI exposes editor.

##11Testing & CI

Layer Tool Gate
Unit xUnit + Moq 50% lines
Integration Testcontainers run in CI Job completes <5s
Style dotnet format 0 warnings

Use the prebaked workflow in StellaOps.Templates as starting point.

##12Publishing to the Community Marketplace

Tag Git release pluginvX.Y.Z and attach the signed ZIP. Submit a PR to stellaops/community-plugins.json with metadata & git URL. On merge, the plugin shows up in the UI Marketplace.

##13Common Pitfalls

Symptom Root cause Fix
NotDetected .sig missing cosign sign …
VersionGateMismatch Backend 2.1 vs plugin 2.0 Recompile / bump attribute
FileLoadException Duplicate StellaOps.Common Ensure PrivateAssets="all"
Redis timeouts Large writes Batch or use Mongo