Skip to content

Commit 560d145

Browse files
committed
feat(tests): add comprehensive logging for debugging fixtures and variable expansion
Added V(2)-V(6) level logging throughout fixture execution to aid debugging: build commands, variable expansion, working directory resolution, and template data transformations. Simplified build execution to run synchronously before fixtures instead of as a task dependency. Added test case documenting logging output.
1 parent 61a69c5 commit 560d145

File tree

5 files changed

+101
-33
lines changed

5 files changed

+101
-33
lines changed

fixtures/expand.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package fixtures
33
import (
44
"fmt"
55
"os"
6+
7+
"github.com/flanksource/commons/logger"
68
)
79

810
// ExpandVars replaces $VAR and ${VAR} references in s with values from vars.
@@ -11,7 +13,9 @@ import (
1113
func ExpandVars(s string, vars map[string]any) string {
1214
return os.Expand(s, func(key string) string {
1315
if v, ok := vars[key]; ok {
14-
return fmt.Sprintf("%v", v)
16+
val := fmt.Sprintf("%v", v)
17+
logger.V(6).Infof("ExpandVars: $%s → %s", key, val)
18+
return val
1519
}
1620
return "$" + key
1721
})

fixtures/runner.go

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package fixtures
22

33
import (
44
"bytes"
5+
"context"
56
"fmt"
67
"os"
78
"os/exec"
@@ -163,21 +164,15 @@ func (r *Runner) executeFixtures() (*FixtureGroup, error) {
163164
Summary: Stats{},
164165
}
165166

166-
// Check if any fixtures need build
167+
// Run build command synchronously before any fixtures
167168
buildCmd := r.getBuildCommand()
168-
var buildTask *clicky.Task
169-
170-
// Create build task if needed (as dependency for other tasks)
171169
if buildCmd != "" {
172-
buildTypedTask := clicky.StartTask[bool](
173-
fmt.Sprintf("Build: %s", buildCmd),
174-
func(ctx flanksourceContext.Context, t *task.Task) (bool, error) {
175-
err := r.executeBuildCommand(ctx, buildCmd)
176-
return err == nil, err
177-
},
178-
clicky.WithTaskTimeout(5*time.Minute),
179-
)
180-
buildTask = buildTypedTask.Task
170+
logger.V(2).Infof("Running build command: %s", buildCmd)
171+
ctx := flanksourceContext.NewContext(context.Background())
172+
if err := r.executeBuildCommand(ctx, buildCmd); err != nil {
173+
return nil, fmt.Errorf("build failed, skipping all fixtures: %w", err)
174+
}
175+
logger.V(2).Infof("Build completed successfully")
181176
}
182177

183178
// Create typed task group for fixture execution
@@ -188,7 +183,7 @@ func (r *Runner) executeFixtures() (*FixtureGroup, error) {
188183
if node.Test != nil {
189184
typedTask := fixtureGroup.Add(node.Test.String(), func(ctx flanksourceContext.Context, t *task.Task) (FixtureResult, error) {
190185
return r.executeFixture(ctx, *node.Test)
191-
}, clicky.WithDependencies(buildTask), clicky.WithTaskTimeout(2*time.Minute))
186+
}, clicky.WithTaskTimeout(2*time.Minute))
192187
taskToNodeMap[typedTask] = node
193188
}
194189
})

fixtures/testdata/logging-paths.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
exec: bash
3+
args: ["-c", "{{.cmd}}"]
4+
build: "echo build-ok"
5+
---
6+
7+
## Build and variable expansion logging
8+
9+
Exercises code paths that produce V(2)-V(6) log output.
10+
Run with -vvvvvv to see all levels.
11+
12+
| Name | cmd | CEL Validation |
13+
|------|-----|----------------|
14+
| build ran | echo ok | exitCode == 0 |
15+
| expand exec var | echo $GOOS | stdout.trim() == GOOS |
16+
| expand arg var | echo $GIT_ROOT_DIR | stdout.trim() == GIT_ROOT_DIR |
17+
| expand multiple | echo $GOOS/$GOARCH | stdout.contains("/") |
18+
19+
## CWD resolution logging
20+
21+
| Name | cwd | cmd | CEL Validation |
22+
|------|-----|-----|----------------|
23+
| relative cwd | . | pwd | exitCode == 0 |
24+
| var in cwd | $GIT_ROOT_DIR | pwd | stdout.trim() == GIT_ROOT_DIR |

fixtures/types.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import (
66
"os/exec"
77
"path/filepath"
88
"runtime"
9+
"sort"
910
"strconv"
1011
"strings"
1112
"time"
1213

1314
"github.com/flanksource/clicky"
1415
"github.com/flanksource/clicky/api"
1516
"github.com/flanksource/clicky/task"
17+
"github.com/flanksource/commons/logger"
1618
"github.com/flanksource/gomplate/v3"
1719
)
1820

@@ -170,6 +172,12 @@ func (e ExecFixtureBase) IsEmpty() bool {
170172
func (e ExecFixtureBase) Template(data map[string]any) (ExecFixtureBase, error) {
171173
var err error
172174

175+
logger.V(5).Infof("Template data keys: %v", sortedKeys(data))
176+
177+
orig := e
178+
origArgs := make([]string, len(e.Args))
179+
copy(origArgs, e.Args)
180+
173181
e.Exec = ExpandVars(e.Exec, data)
174182
if e.Exec, err = gomplate.RunTemplate(data, gomplate.Template{
175183
Template: e.Exec,
@@ -200,9 +208,41 @@ func (e ExecFixtureBase) Template(data map[string]any) (ExecFixtureBase, error)
200208
return ExecFixtureBase{}, err
201209
}
202210
}
211+
212+
// Log a single consolidated summary of all changed fields
213+
if logger.IsLevelEnabled(4) {
214+
var changes []string
215+
if e.Exec != orig.Exec {
216+
changes = append(changes, fmt.Sprintf("exec: %q→%q", orig.Exec, e.Exec))
217+
}
218+
if e.Build != orig.Build {
219+
changes = append(changes, fmt.Sprintf("build: %q→%q", orig.Build, e.Build))
220+
}
221+
if e.CWD != orig.CWD {
222+
changes = append(changes, fmt.Sprintf("cwd: %q→%q", orig.CWD, e.CWD))
223+
}
224+
for i, a := range e.Args {
225+
if i < len(origArgs) && a != origArgs[i] {
226+
changes = append(changes, fmt.Sprintf("args[%d]: %q→%q", i, origArgs[i], a))
227+
}
228+
}
229+
if len(changes) > 0 {
230+
logger.V(4).Infof("Template: %s", strings.Join(changes, ", "))
231+
}
232+
}
233+
203234
return e, nil
204235
}
205236

237+
func sortedKeys(m map[string]any) []string {
238+
keys := make([]string, 0, len(m))
239+
for k := range m {
240+
keys = append(keys, k)
241+
}
242+
sort.Strings(keys)
243+
return keys
244+
}
245+
206246
func (e ExecFixtureBase) AsMap() map[string]string {
207247
envMap := map[string]string{}
208248
if e.CWD != "" {
@@ -433,6 +473,14 @@ func (f FixtureResult) Pretty() api.Text {
433473
isFailed := f.Status == task.StatusFAIL || f.Status == task.StatusERR || f.Status == task.StatusFailed
434474
verbosity := clicky.Flags.LevelCount
435475

476+
if verbosity >= 2 && f.Command != "" {
477+
cmd := f.Command
478+
if f.CWD != "" {
479+
cmd += " (cwd: " + relativePath(f.CWD) + ")"
480+
}
481+
t = t.Append("$ "+cmd, "text-gray-500")
482+
}
483+
436484
if isFailed {
437485
switch {
438486
case verbosity >= 2:

fixtures/types/exec.go

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ func (e *ExecFixture) Run(ctx context.Context, fixture fixtures.FixtureTest, opt
5050
rootDir = baseDir
5151
}
5252

53+
if gitRoot != goRoot {
54+
logger.V(3).Infof("Directories: base=%s git=%s go=%s root=%s", baseDir, gitRoot, goRoot, rootDir)
55+
}
56+
5357
// Inject auto-injected vars into TemplateVars so they're available
5458
// in both Template() expansion and CEL evaluation via AsMap()
5559
if fixture.TemplateVars == nil {
@@ -88,6 +92,9 @@ func (e *ExecFixture) Run(ctx context.Context, fixture fixtures.FixtureTest, opt
8892
workDir = filepath.Join(baseDir, exec.CWD)
8993
}
9094
}
95+
if workDir != baseDir {
96+
logger.V(3).Infof("WorkDir: %s (expanded from %s)", workDir, exec.CWD)
97+
}
9198

9299
if exec.Env == nil {
93100
exec.Env = make(map[string]any)
@@ -98,19 +105,6 @@ func (e *ExecFixture) Run(ctx context.Context, fixture fixtures.FixtureTest, opt
98105
}
99106
}
100107

101-
bash := clicky.Exec("bash", "-c").AsWrapper()
102-
103-
// Execute build command if specified (but skip it in task mode since build task handles it)
104-
if exec.Build != "" {
105-
logger.V(4).Infof("🔨 Build command: %s", exec.Build)
106-
107-
p, err := bash(exec.Build)
108-
if err != nil {
109-
return result.Errorf(err, "build failed: %s", p.Pretty().ANSI())
110-
}
111-
112-
}
113-
114108
if exec.Exec == "" {
115109
return result.Errorf(fmt.Errorf("no command specified"), "no command specified")
116110
}
@@ -190,13 +184,16 @@ func ResolveWorkDir(fixture fixtures.FixtureTest, opts fixtures.RunOptions) stri
190184

191185
// Get the merged CWD (file-level frontmatter + test-level override)
192186
cwd := fixture.ExecBase().CWD
187+
var result string
193188
if cwd == "" || cwd == "." {
194-
return baseDir
195-
}
196-
if filepath.IsAbs(cwd) {
197-
return cwd
189+
result = baseDir
190+
} else if filepath.IsAbs(cwd) {
191+
result = cwd
192+
} else {
193+
result = filepath.Join(baseDir, cwd)
198194
}
199-
return filepath.Join(baseDir, cwd)
195+
logger.V(4).Infof("ResolveWorkDir: opts.WorkDir=%s sourceDir=%s cwd=%s → %s", opts.WorkDir, fixture.SourceDir, cwd, result)
196+
return result
200197
}
201198

202199
// GetRequiredFields returns required fields

0 commit comments

Comments
 (0)