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
15 changes: 2 additions & 13 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,7 @@ var validateCmd = &cobra.Command{
return runValidation(yamlRecipe)
}

// Check base recipes
for _, recipe := range recipes {
if recipe.Name() == recipeName {
return runValidation(recipe)
}
}

return fmt.Errorf("recipe '%s' not found", recipeName)
return fmt.Errorf("recipe file '%s' not found", recipeName)
},
}

Expand Down Expand Up @@ -523,11 +516,7 @@ var testCmd = &cobra.Command{
},
}

var recipes = []playground.Recipe{
&playground.L1Recipe{},
&playground.OpRecipe{},
&playground.BuilderNetRecipe{},
}
var recipes = playground.GetBaseRecipes()

func main() {
// Set the embedded custom recipes filesystem for the playground package
Expand Down
15 changes: 15 additions & 0 deletions playground/cmd_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,27 @@ func ValidateRecipe(recipe Recipe, baseRecipes []Recipe) *ValidationResult {
validateYAMLRecipe(yamlRecipe, baseRecipes, result)
}

// Create a temp output directory for validation
tmpDir, err := os.MkdirTemp("", "playground-validate-")
if err != nil {
result.AddError("failed to create temp directory: %v", err)
return result
}
defer os.RemoveAll(tmpDir)

out, err := NewOutput(tmpDir)
if err != nil {
result.AddError("failed to create output: %v", err)
return result
}

// Build a minimal manifest to validate structure
exCtx := &ExContext{
LogLevel: LevelInfo,
Contender: &ContenderContext{
Enabled: false,
},
Output: out,
}

component := recipe.Apply(exCtx)
Expand Down
57 changes: 57 additions & 0 deletions playground/custom_recipes_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
package playground

import (
"io/fs"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"testing/fstest"

flag "github.com/spf13/pflag"
"github.com/stretchr/testify/require"
)

// getRepoRootFS returns an fs.FS rooted at the repository root for testing real custom-recipes
func getRepoRootFS(t *testing.T) fs.FS {
t.Helper()
_, filename, _, ok := runtime.Caller(0)
require.True(t, ok, "failed to get caller info")
// Go up from playground/ to repo root
repoRoot := filepath.Dir(filepath.Dir(filename))
return os.DirFS(repoRoot)
}

func newTestCustomRecipesFS() fstest.MapFS {
return fstest.MapFS{
// Recipes in group/variant/playground.yaml format
Expand Down Expand Up @@ -439,3 +452,47 @@ func (m *mockRecipe) Apply(ctx *ExContext) *Component {
func (m *mockRecipe) Output(manifest *Manifest) map[string]interface{} {
return nil
}

func TestValidateBaseRecipes(t *testing.T) {
baseRecipes := GetBaseRecipes()
require.NotEmpty(t, baseRecipes)

for _, recipe := range baseRecipes {
t.Run(recipe.Name(), func(t *testing.T) {
result := ValidateRecipe(recipe, baseRecipes)
require.Empty(t, result.Errors, "base recipe %s has validation errors: %v", recipe.Name(), result.Errors)
})
}
}

func TestValidateShippedCustomRecipes(t *testing.T) {
// Validate real custom-recipes that ship with the binary
original := CustomRecipesFS
CustomRecipesFS = getRepoRootFS(t)
defer func() { CustomRecipesFS = original }()

baseRecipes := GetBaseRecipes()

customRecipes, err := GetEmbeddedCustomRecipes()
require.NoError(t, err)
require.NotEmpty(t, customRecipes)

for _, name := range customRecipes {
t.Run(name, func(t *testing.T) {
recipe, cleanup, err := LoadCustomRecipe(name, baseRecipes)
require.NoError(t, err)
defer cleanup()

result := ValidateRecipe(recipe, baseRecipes)

// Filter host_path errors (environment-specific)
var errs []string
for _, e := range result.Errors {
if !strings.Contains(e, "host_path does not exist") {
errs = append(errs, e)
}
}
Comment on lines +488 to +494
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The host_path error filter silently hides these errors. Consider adding t.Logf for filtered errors so they're visible in verbose test output (go test -v), making it easier to notice when a recipe has environment-specific issues:

Suggested change
// Filter host_path errors (environment-specific)
var errs []string
for _, e := range result.Errors {
if !strings.Contains(e, "host_path does not exist") {
errs = append(errs, e)
}
}
var errs []string
for _, e := range result.Errors {
if strings.Contains(e, "host_path does not exist") {
t.Logf("filtered environment-specific error: %s", e)
} else {
errs = append(errs, e)
}
}

require.Empty(t, errs, "validation errors: %v", errs)
})
}
}
9 changes: 9 additions & 0 deletions playground/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ type Recipe interface {
Output(manifest *Manifest) map[string]interface{}
}

// GetBaseRecipes returns all available base recipes
func GetBaseRecipes() []Recipe {
return []Recipe{
&L1Recipe{},
&OpRecipe{},
&BuilderNetRecipe{},
}
}

// Manifest describes a list of services and their dependencies
type Manifest struct {
ID string `json:"session_id"`
Expand Down
22 changes: 11 additions & 11 deletions playground/recipe_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ recipe:
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)

Expand All @@ -457,7 +457,7 @@ func TestParseYAMLRecipe_MissingBase(t *testing.T) {
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

_, err = ParseYAMLRecipe(yamlFile, baseRecipes)

Expand All @@ -476,7 +476,7 @@ recipe: {}
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

_, err = ParseYAMLRecipe(yamlFile, baseRecipes)

Expand All @@ -485,7 +485,7 @@ recipe: {}
}

func TestParseYAMLRecipe_FileNotFound(t *testing.T) {
baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

_, err := ParseYAMLRecipe("/nonexistent/path/recipe.yaml", baseRecipes)

Expand All @@ -503,7 +503,7 @@ recipe: {}
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)
require.NoError(t, err)
Expand All @@ -527,7 +527,7 @@ recipe:
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)
require.NoError(t, err)
Expand Down Expand Up @@ -558,7 +558,7 @@ recipe:
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)
require.NoError(t, err)
Expand Down Expand Up @@ -592,7 +592,7 @@ recipe:
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)
require.NoError(t, err)
Expand Down Expand Up @@ -627,7 +627,7 @@ recipe:
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)
require.NoError(t, err)
Expand Down Expand Up @@ -708,7 +708,7 @@ recipe: {}
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)
require.NoError(t, err)
Expand Down Expand Up @@ -738,7 +738,7 @@ recipe:
yamlFile := filepath.Join(tmpDir, "recipe.yaml")
require.NoError(t, os.WriteFile(yamlFile, []byte(yamlContent), 0o644))

baseRecipes := []Recipe{&L1Recipe{}}
baseRecipes := GetBaseRecipes()

recipe, err := ParseYAMLRecipe(yamlFile, baseRecipes)
require.NoError(t, err)
Expand Down