diff --git a/server/internal/models/workflow.go b/server/internal/models/workflow.go index 3c03019..9880c56 100644 --- a/server/internal/models/workflow.go +++ b/server/internal/models/workflow.go @@ -22,12 +22,15 @@ type WorkflowStep struct { DeclaredOutputs []string `bson:"declared_outputs" json:"declared_outputs"` DeclaredInputs []InputParam `bson:"declared_inputs" json:"declared_inputs"` SecretRefs []string `bson:"secret_refs" json:"secret_refs"` + Source string `bson:"source" json:"source"` // "user" | "default" + Slug string `bson:"slug,omitempty" json:"slug,omitempty"` CreatedAt time.Time `bson:"created_at" json:"created_at"` UpdatedAt time.Time `bson:"updated_at" json:"updated_at"` } type WorkflowStepRef struct { - StepID string `bson:"step_id" json:"step_id"` + StepID string `bson:"step_id,omitempty" json:"step_id,omitempty"` + Inline *WorkflowStep `bson:"inline,omitempty" json:"inline,omitempty"` Order int `bson:"order" json:"order"` OnFailure string `bson:"on_failure" json:"on_failure"` // "stop" | "continue" | "retry" MaxRetries int `bson:"max_retries" json:"max_retries"` diff --git a/server/internal/services/validate.go b/server/internal/services/validate.go new file mode 100644 index 0000000..c2bf6c5 --- /dev/null +++ b/server/internal/services/validate.go @@ -0,0 +1,19 @@ +package services + +import ( + "fmt" + + "github.com/mrhid6/vantage/server/internal/models" +) + +// ValidateWorkflow checks each step ref sets exactly one of step_id / inline. +func ValidateWorkflow(w models.Workflow) error { + for i, ref := range w.Steps { + hasLib := ref.StepID != "" + hasInline := ref.Inline != nil + if hasLib == hasInline { + return fmt.Errorf("step %d: exactly one of step_id or inline must be set", i) + } + } + return nil +} diff --git a/server/internal/services/validate_test.go b/server/internal/services/validate_test.go new file mode 100644 index 0000000..8121e16 --- /dev/null +++ b/server/internal/services/validate_test.go @@ -0,0 +1,29 @@ +package services + +import ( + "testing" + + "github.com/mrhid6/vantage/server/internal/models" +) + +func TestValidateWorkflow(t *testing.T) { + inline := &models.WorkflowStep{Name: "x", Interpreter: "bash", Script: "echo hi"} + cases := []struct { + name string + ref models.WorkflowStepRef + wantErr bool + }{ + {"library only", models.WorkflowStepRef{StepID: "abc"}, false}, + {"inline only", models.WorkflowStepRef{Inline: inline}, false}, + {"both set", models.WorkflowStepRef{StepID: "abc", Inline: inline}, true}, + {"neither set", models.WorkflowStepRef{}, true}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + err := ValidateWorkflow(models.Workflow{Steps: []models.WorkflowStepRef{tc.ref}}) + if (err != nil) != tc.wantErr { + t.Fatalf("got err=%v want wantErr=%v", err, tc.wantErr) + } + }) + } +}