Add transform resolver wiring

This commit is contained in:
2026-05-31 03:30:08 +00:00
parent be4a61fbe6
commit f2ec7bd11e
7 changed files with 113 additions and 8 deletions

View File

@@ -19,7 +19,11 @@ func PlanOutputs(ctx context.Context, req Request) ([]Output, error) {
outputs = append(outputs, sourceOutputs...)
}
if req.Publish.HTML {
generatedOutputs, err := markdownTransformer().Generate(ctx, transform.Request{
transformer, err := resolveTransformer(req.Transformers, transform.MarkdownToHTML)
if err != nil {
return nil, err
}
generatedOutputs, err := transformer.Generate(ctx, transform.Request{
SourceBundle: req.SourceBundle,
SourceBackend: req.SourceBackend,
})
@@ -47,6 +51,17 @@ func PlanOutputs(ctx context.Context, req Request) ([]Output, error) {
return outputs, nil
}
func resolveTransformer(resolver TransformerResolver, name string) (transform.Transformer, error) {
if resolver == nil {
return nil, fmt.Errorf("transformer resolver is required for %s", name)
}
transformer, ok := resolver.Get(name)
if !ok {
return nil, fmt.Errorf("transformer %s is not registered", name)
}
return transformer, nil
}
func PlanSourceOutputs(req Request) ([]Output, error) {
outputs := make([]Output, 0, len(req.SourceBundle.Manifest.Files))
for _, file := range req.SourceBundle.Manifest.Files {

View File

@@ -9,6 +9,7 @@ import (
"gitea.maximumdirect.net/eric/distributor/internal/config"
"gitea.maximumdirect.net/eric/distributor/internal/storage"
"gitea.maximumdirect.net/eric/distributor/internal/storage/fake"
"gitea.maximumdirect.net/eric/distributor/internal/transform"
)
func TestPlanOutputsRejectsCollision(t *testing.T) {
@@ -38,6 +39,14 @@ func TestPlanOutputsRejectsCollision(t *testing.T) {
},
Publish: config.PublishPolicy{Source: true, HTML: true},
Transform: config.Transform{MarkdownToHTML: &config.MarkdownToHTML{Enabled: true, Mode: config.TransformModeSidecar}},
Transformers: testResolver{transform.MarkdownToHTML: testTransformer{outputs: []transform.Output{{
Path: "report.html",
SourcePath: "report.md",
Transform: transform.MarkdownToHTML,
Data: []byte("<p>Report</p>\n"),
SHA256: bundle.FileDigest([]byte("<p>Report</p>\n")),
Size: int64(len("<p>Report</p>\n")),
}}}},
})
if err == nil {
t.Fatal("PlanSourceOutputs() error = nil, want collision")
@@ -61,12 +70,61 @@ func TestPlanOutputsRejectsHTMLWithoutMarkdown(t *testing.T) {
}},
Publish: config.PublishPolicy{HTML: true},
Transform: config.Transform{MarkdownToHTML: &config.MarkdownToHTML{Enabled: true, Mode: config.TransformModeSidecar}},
Transformers: testResolver{
transform.MarkdownToHTML: testTransformer{},
},
})
if err == nil {
t.Fatal("PlanOutputs() error = nil, want no markdown failure")
}
}
func TestPlanOutputsRejectsHTMLWithoutTransformerResolver(t *testing.T) {
_, err := PlanOutputs(context.Background(), Request{
Publish: config.PublishPolicy{HTML: true},
Transform: config.Transform{MarkdownToHTML: &config.MarkdownToHTML{Enabled: true, Mode: config.TransformModeSidecar}},
})
if err == nil {
t.Fatal("PlanOutputs() error = nil, want resolver failure")
}
}
func TestPlanOutputsRejectsMissingMarkdownTransformer(t *testing.T) {
_, err := PlanOutputs(context.Background(), Request{
Publish: config.PublishPolicy{HTML: true},
Transform: config.Transform{MarkdownToHTML: &config.MarkdownToHTML{Enabled: true, Mode: config.TransformModeSidecar}},
Transformers: testResolver{},
})
if err == nil {
t.Fatal("PlanOutputs() error = nil, want missing transformer failure")
}
}
func TestPlanOutputsUsesRegisteredTransformer(t *testing.T) {
data := []byte("<p>Generated</p>\n")
outputs, err := PlanOutputs(context.Background(), Request{
Publish: config.PublishPolicy{HTML: true},
Transform: config.Transform{MarkdownToHTML: &config.MarkdownToHTML{Enabled: true, Mode: config.TransformModeSidecar}},
Transformers: testResolver{transform.MarkdownToHTML: testTransformer{outputs: []transform.Output{{
Path: "report.html",
SourcePath: "report.md",
Transform: transform.MarkdownToHTML,
Data: data,
SHA256: bundle.FileDigest(data),
Size: int64(len(data)),
}}}},
})
if err != nil {
t.Fatalf("PlanOutputs() error = %v", err)
}
if got, want := len(outputs), 1; got != want {
t.Fatalf("output count = %d, want %d", got, want)
}
if outputs[0].DestinationPath != "report.html" || string(outputs[0].Data) != string(data) {
t.Fatalf("output = %#v", outputs[0])
}
}
func TestBuildRejectsHTMLWithoutTransform(t *testing.T) {
sourceBackend := fake.New()
destinationBackend := fake.New()
@@ -208,3 +266,19 @@ func TestValidateRequestChecksPublishTransformPolicy(t *testing.T) {
})
}
}
type testResolver map[string]transform.Transformer
func (r testResolver) Get(name string) (transform.Transformer, bool) {
transformer, ok := r[name]
return transformer, ok
}
type testTransformer struct {
outputs []transform.Output
err error
}
func (t testTransformer) Generate(context.Context, transform.Request) ([]transform.Output, error) {
return t.outputs, t.err
}

View File

@@ -9,7 +9,6 @@ import (
"gitea.maximumdirect.net/eric/distributor/internal/state"
"gitea.maximumdirect.net/eric/distributor/internal/storage"
"gitea.maximumdirect.net/eric/distributor/internal/transform"
markdowntransform "gitea.maximumdirect.net/eric/distributor/internal/transform/markdown"
)
type Action string
@@ -32,10 +31,15 @@ type Request struct {
DestinationBundlePath string
Publish config.PublishPolicy
Transform config.Transform
Transformers TransformerResolver
Transfer config.TransferPolicy
DistributorVersion string
}
type TransformerResolver interface {
Get(name string) (transform.Transformer, bool)
}
type Plan struct {
PipelineID string
DestinationID string
@@ -108,10 +112,6 @@ func validateRequest(req Request) error {
return nil
}
func markdownTransformer() transform.Transformer {
return markdowntransform.New()
}
func actionForComparison(comparison state.Comparison, transfer config.TransferPolicy) (Action, string) {
switch comparison.Outcome {
case state.OutcomeDestinationAbsent: