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
22 changes: 16 additions & 6 deletions internal/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -1106,12 +1106,7 @@ func runAgent(ctx context.Context, agentName, fullsendDir, outputBase, targetRep
printer.StepStart("Running validation: " + h.ValidationLoop.Script)
valCmd := exec.Command(h.ValidationLoop.Script)
valCmd.Dir = iterDir
valCmd.Env = append(os.Environ(),
append(envToList(h.RunnerEnv),
fmt.Sprintf("TARGET_REPO_DIR=%s", hostRepositoryDir),
fmt.Sprintf("FULLSEND_RUN_DIR=%s", runDir),
)...,
)
valCmd.Env = append(os.Environ(), validationEnv(h, hostRepositoryDir, runDir)...)
valOut, valErr := valCmd.CombinedOutput()

if valErr == nil {
Expand Down Expand Up @@ -1698,6 +1693,21 @@ func childScriptEnv(runnerEnv map[string]string, traceparent string) []string {
return env
}

// validationEnv builds the extra environment entries for the validation
// script. It includes RunnerEnv, TARGET_REPO_DIR, FULLSEND_RUN_DIR, and —
// when the harness specifies a validation_loop.schema — FULLSEND_OUTPUT_SCHEMA
// pointing to the host-side cached schema path.
func validationEnv(h *harness.Harness, hostRepoDir, runDir string) []string {
env := append(envToList(h.RunnerEnv),
fmt.Sprintf("TARGET_REPO_DIR=%s", hostRepoDir),
fmt.Sprintf("FULLSEND_RUN_DIR=%s", runDir),
)
if h.ValidationLoop != nil && h.ValidationLoop.Schema != "" {
env = append(env, fmt.Sprintf("FULLSEND_OUTPUT_SCHEMA=%s", h.ValidationLoop.Schema))
Comment thread
ggallen marked this conversation as resolved.
}
return env
}

func envToList(env map[string]string) []string {
keys := make([]string, 0, len(env))
for k := range env {
Expand Down
40 changes: 40 additions & 0 deletions internal/cli/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,46 @@ func TestValidationFailMessage_TrimsOutput(t *testing.T) {
assert.Equal(t, "some output", msg)
}

func TestValidationEnv_IncludesSchemaWhenSet(t *testing.T) {
h := &harness.Harness{
RunnerEnv: map[string]string{"FOO": "bar"},
ValidationLoop: &harness.ValidationLoop{
Script: "scripts/validate.sh",
Schema: "/tmp/test-schema.json",
},
}
env := validationEnv(h, "/repo", "/run")
assert.Contains(t, env, "FULLSEND_OUTPUT_SCHEMA=/tmp/test-schema.json")
assert.Contains(t, env, "TARGET_REPO_DIR=/repo")
assert.Contains(t, env, "FULLSEND_RUN_DIR=/run")
assert.Contains(t, env, "FOO=bar")
}

func TestValidationEnv_OmitsSchemaWhenEmpty(t *testing.T) {
h := &harness.Harness{
RunnerEnv: map[string]string{"FOO": "bar"},
ValidationLoop: &harness.ValidationLoop{
Script: "scripts/validate.sh",
},
}
env := validationEnv(h, "/repo", "/run")
for _, e := range env {
assert.False(t, strings.HasPrefix(e, "FULLSEND_OUTPUT_SCHEMA="),
"FULLSEND_OUTPUT_SCHEMA should not be set when Schema is empty")
}
}

func TestValidationEnv_OmitsSchemaWhenNoValidationLoop(t *testing.T) {
h := &harness.Harness{
RunnerEnv: map[string]string{"FOO": "bar"},
}
env := validationEnv(h, "/repo", "/run")
for _, e := range env {
assert.False(t, strings.HasPrefix(e, "FULLSEND_OUTPUT_SCHEMA="),
"FULLSEND_OUTPUT_SCHEMA should not be set when ValidationLoop is nil")
}
}

func TestOpenTeeReader_EmptyPath(t *testing.T) {
src := strings.NewReader("hello")
printer := ui.New(io.Discard)
Expand Down
Loading