Guia — IStep
Um passo novo de pipeline, ativado por uma chave em type: no YAML. É o ponto de extensão mais
usado.
Exemplo mínimo
using System.Text.Json.Nodes;
using Pipevine.Abstractions;
// A chave usada no YAML: `type: acme.echo`
[Step("acme.echo")]
public sealed class EchoStepFactory : IStepFactory
{
// Roda UMA vez, no startup. Valida a config, resolve o que precisa ser resolvido uma
// vez só. Lançar aqui derruba a aplicação — não a primeira requisição.
public IStep Build(StepBuildContext context)
{
var message = context.Config["message"]?.GetValue<string>()
?? throw new InvalidOperationException("'acme.echo' requer 'message'.");
return new EchoStep(message);
}
}
// Imutável, thread-safe, reusado por toda requisição — nenhum campo mutável (PV4002 pega isso).
internal sealed class EchoStep(string message) : IStep
{
public ValueTask<StepOutcome> ExecuteAsync(PipelineContext ctx, CancellationToken ct)
{
ctx.Vars()["echo"] = JsonValue.Create(message);
return ValueTask.FromResult(StepOutcome.Continue);
}
}
pipeline:
- type: acme.echo
message: "hello"
Ativação
Referenciar o pacote (
<PackageReference Include="Acme.Pipevine.Extension" />).Nenhum passo 2 para o caminho compilado —
[Step("acme.echo")]é descoberto automaticamente pelo gerador de código a partir das referências de compilação, então o step já é validado em tempo de build (umtype:desconhecido vira o diagnósticoPV3001, apontando para o YAML) sem nenhum registro manual.Mas para o modo interpretado em runtime, o autor da aplicação ainda precisa registrar a factory no DI — por convenção, num método
AddXxx()que o próprio pacote expõe:services.AddKeyedSingleton<IStepFactory, EchoStepFactory>("acme.echo");A razão para esse passo extra:
[Step]alimenta só o catálogo de compile-time do gerador de código; o registro que resolve steps em runtime para o caminho interpretado é um mecanismo de DI separado, resolvido por chave. As duas coisas coexistem porque servem dois caminhos de execução diferentes — compilado e interpretado — e cada um precisa do seu próprio registro.
Validação de config com schema (opcional)
Implemente IStepConfigSchema ao lado de IStepFactory para declarar um JSON Schema do bloco
config: — sem isso o step funciona normalmente, só perde a validação de YAML no formato de schema
(PV4010 avisa, não bloqueia):
public sealed class EchoStepFactory : IStepFactory, IStepConfigSchema
{
public string ConfigJsonSchema =>
"""{ "type": "object", "required": ["message"], "properties": { "message": { "type": "string" } } }""";
public IStep Build(StepBuildContext context) { /* ... */ }
}
Participando da geração de código (opcional)
Um step pode implementar IStepCodeEmitter para emitir C# direto em vez do caminho interpretado
genérico dentro de um pipeline gerado — ver IStepCodeEmitter. Nenhum step é
obrigado a isso: extensibilidade nunca é bloqueada por performance.
Diagnósticos para quem escreve o step
Referencie o analisador Roslyn do Pipevine (PrivateAssets="all") no .csproj do seu pacote de
extensão:
PV4001—IStepFactorysem[Step].PV4002— campo ou propriedade mutável numa implementação deIStep.PV4010—IStepFactorysemIStepConfigSchema(aviso).PV4020— chave de step colidindo com uma já registrada, sua ou de um pacote referenciado.
Para onde ir daqui
- Visão geral de extensibilidade
IStepCodeEmitter— caminho rápido opcional de compile-time