Carry dependencies through pipeline commands

This commit is contained in:
2026-09-05 17:53:56 +00:00
parent c3307ab5fb
commit dd905c4daa
13 changed files with 153 additions and 89 deletions

View File

@@ -25,11 +25,12 @@ inputs:
prefix: audio/
`)
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{filepath.Join(t.TempDir(), "session.yml")})
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := fakeCommandDependencies(fake, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code != 0 {
t.Fatalf("exit code = %d, want 0; stderr=%q", code, stderr.String())
}
@@ -154,7 +155,8 @@ inputs:
fake := &storage.FakeBackend{}
seedRemoteSessionConfig(t, fake, "2026-05-03", tt.sessionYAML)
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{filepath.Join(t.TempDir(), "session.yml")})
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := fakeCommandDependencies(fake, &storeInitCalls)
tempRoot := t.TempDir()
t.Setenv("TMPDIR", tempRoot)
@@ -166,7 +168,7 @@ inputs:
args := append(append([]string(nil), tt.command...), "--config", pipelinePath, "--campaign-file", campaignPath)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := executeWithPipelineExecutor(args, &stdout, &stderr, executor)
code := executeWithDependencies(args, &stdout, &stderr, deps, executor)
if tt.wantSuccessful && code != 0 {
t.Fatalf("exit code = %d, want 0; stderr=%q", code, stderr.String())
}
@@ -243,23 +245,17 @@ inputs:
audio_s3:
prefix: audio/
`)
origStoreFn := newObjectStoreFromConfigFn
origSessionDefaults := append([]string(nil), config.DefaultSessionConfigSearchPaths...)
config.DefaultSessionConfigSearchPaths = []string{filepath.Join(t.TempDir(), "session.yml")}
newObjectStoreFromConfigFn = func(context.Context, *config.Config) (storage.ObjectStore, error) {
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := commandDependencies{newObjectStore: func(context.Context, *config.Config) (storage.ObjectStore, error) {
if os.Getenv(accessKeyEnv) != "remote-session-key-id" || os.Getenv(secretKeyEnv) != "remote-session-secret" {
return nil, fmt.Errorf("secrets were not loaded before remote session object store init")
}
return fake, nil
}
t.Cleanup(func() {
newObjectStoreFromConfigFn = origStoreFn
config.DefaultSessionConfigSearchPaths = origSessionDefaults
})
}}
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code != 0 {
t.Fatalf("exit code = %d, want 0; stdout=%q stderr=%q", code, stdout.String(), stderr.String())
}
@@ -270,11 +266,12 @@ func TestExecuteExplicitLocalSessionPrecedenceSkipsRemote(t *testing.T) {
pipelinePath, campaignPath, sessionPath := writeValidConfigFiles(t, workspaceRoot)
fake := &storage.FakeBackend{}
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{filepath.Join(t.TempDir(), "session.yml")})
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := fakeCommandDependencies(fake, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath, "--session", sessionPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath, "--session", sessionPath}, &stdout, &stderr, deps, executePlan)
if code != 0 {
t.Fatalf("exit code = %d, want 0; stderr=%q", code, stderr.String())
}
@@ -288,11 +285,12 @@ func TestExecuteLocalSessionDiscoveryPrecedenceSkipsRemote(t *testing.T) {
pipelinePath, campaignPath, sessionPath := writeValidConfigFiles(t, workspaceRoot)
fake := &storage.FakeBackend{}
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{sessionPath})
setSessionConfigSearchPaths(t, []string{sessionPath})
deps := fakeCommandDependencies(fake, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code != 0 {
t.Fatalf("exit code = %d, want 0; stderr=%q", code, stderr.String())
}
@@ -307,11 +305,12 @@ func TestExecuteRemoteSessionMissingObjectFailsClearly(t *testing.T) {
fake := &storage.FakeBackend{}
var storeInitCalls int
missingSessionPath := filepath.Join(t.TempDir(), "session.yml")
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{missingSessionPath})
setSessionConfigSearchPaths(t, []string{missingSessionPath})
deps := fakeCommandDependencies(fake, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code == 0 {
t.Fatal("exit code = 0, want non-zero")
}
@@ -327,11 +326,12 @@ func TestExecuteRemoteSessionRequiresSessionID(t *testing.T) {
workspaceRoot := t.TempDir()
pipelinePath, campaignPath, _ := writeValidConfigFiles(t, workspaceRoot)
var storeInitCalls int
restoreAppConfigTestGlobals(t, &storage.FakeBackend{}, &storeInitCalls, []string{filepath.Join(t.TempDir(), "session.yml")})
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := fakeCommandDependencies(&storage.FakeBackend{}, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code == 0 {
t.Fatal("exit code = 0, want non-zero")
}
@@ -346,20 +346,14 @@ func TestExecuteRemoteSessionRequiresSessionID(t *testing.T) {
func TestExecuteRemoteSessionStorageInitErrorFailsClearly(t *testing.T) {
workspaceRoot := t.TempDir()
pipelinePath, campaignPath, _ := writeValidConfigFiles(t, workspaceRoot)
origStoreFn := newObjectStoreFromConfigFn
origSessionDefaults := append([]string(nil), config.DefaultSessionConfigSearchPaths...)
config.DefaultSessionConfigSearchPaths = []string{filepath.Join(t.TempDir(), "session.yml")}
newObjectStoreFromConfigFn = func(context.Context, *config.Config) (storage.ObjectStore, error) {
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := commandDependencies{newObjectStore: func(context.Context, *config.Config) (storage.ObjectStore, error) {
return nil, errors.New("storage unavailable")
}
t.Cleanup(func() {
newObjectStoreFromConfigFn = origStoreFn
config.DefaultSessionConfigSearchPaths = origSessionDefaults
})
}}
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code == 0 {
t.Fatal("exit code = 0, want non-zero")
}
@@ -374,11 +368,12 @@ func TestExecuteRemoteSessionMalformedYAMLFailsStrictDecode(t *testing.T) {
fake := &storage.FakeBackend{}
seedRemoteSessionConfig(t, fake, "2026-05-03", "session_id: 2026-05-03\nunknown: true\n")
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{filepath.Join(t.TempDir(), "session.yml")})
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := fakeCommandDependencies(fake, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code == 0 {
t.Fatal("exit code = 0, want non-zero")
}
@@ -397,11 +392,12 @@ inputs:
prefix: audio/
`)
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{filepath.Join(t.TempDir(), "session.yml")})
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := fakeCommandDependencies(fake, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code == 0 {
t.Fatal("exit code = 0, want non-zero")
}
@@ -416,11 +412,12 @@ func TestExecuteRemoteSessionMismatchFails(t *testing.T) {
fake := &storage.FakeBackend{}
seedRemoteSessionConfig(t, fake, "2026-05-03", "session_id: 2026-05-04\ninputs:\n audio_s3:\n prefix: audio/\n")
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{filepath.Join(t.TempDir(), "session.yml")})
setSessionConfigSearchPaths(t, []string{filepath.Join(t.TempDir(), "session.yml")})
deps := fakeCommandDependencies(fake, &storeInitCalls)
var stdout bytes.Buffer
var stderr bytes.Buffer
code := Execute([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr)
code := executeWithDependencies([]string{"session", "plan", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath}, &stdout, &stderr, deps, executePlan)
if code == 0 {
t.Fatal("exit code = 0, want non-zero")
}
@@ -448,12 +445,16 @@ func restoreAppConfigTestGlobals(t *testing.T, fake *storage.FakeBackend, storeI
func remoteSessionLoaderDependencies(fake *storage.FakeBackend) (commandDependencies, *int) {
storeInitCalls := new(int)
return commandDependencies{
newObjectStore: func(context.Context, *config.Config) (storage.ObjectStore, error) {
return fakeCommandDependencies(fake, storeInitCalls), storeInitCalls
}
func fakeCommandDependencies(fake *storage.FakeBackend, storeInitCalls *int) commandDependencies {
return commandDependencies{newObjectStore: func(context.Context, *config.Config) (storage.ObjectStore, error) {
if storeInitCalls != nil {
*storeInitCalls++
return fake, nil
},
}, storeInitCalls
}
return fake, nil
}}
}
func setSessionConfigSearchPaths(t *testing.T, paths []string) {