Carry dependencies through config commands

This commit is contained in:
2026-09-05 18:48:25 +00:00
parent 0726786016
commit 9bb203476d
3 changed files with 61 additions and 12 deletions

View File

@@ -48,7 +48,7 @@ func executeWithDependencies(args []string, stdout, stderr io.Writer, deps comma
case "clean":
err = cleanWithDependencies(ctx, cmdArgs, stdout, deps)
case "config":
err = Config(ctx, cmdArgs, stdout)
err = configWithDependencies(ctx, cmdArgs, stdout, deps)
default:
fmt.Fprintf(stderr, "unknown command: %q\n\n", cmd)
printUsage(stderr)

View File

@@ -29,6 +29,11 @@ type inspectionConfig struct {
// Config dispatches read-only pipeline configuration commands.
func Config(ctx context.Context, args []string, out io.Writer) error {
return configWithDependencies(ctx, args, out, commandDependencies{})
}
func configWithDependencies(ctx context.Context, args []string, out io.Writer, deps commandDependencies) error {
deps = normalizeCommandDependencies(deps)
if len(args) == 0 {
return fmt.Errorf("config: expected subcommand: validate|show|sources|diff")
}
@@ -38,11 +43,11 @@ func Config(ctx context.Context, args []string, out io.Writer) error {
}
switch args[0] {
case "validate":
return ConfigValidate(ctx, args[1:], out)
return configValidateWithDependencies(ctx, args[1:], out, deps)
case "show":
return ConfigShow(ctx, args[1:], out)
return configShowWithDependencies(ctx, args[1:], out, deps)
case "sources":
return ConfigSources(ctx, args[1:], out)
return configSourcesWithDependencies(ctx, args[1:], out, deps)
case "diff":
return ConfigDiff(ctx, args[1:], out)
default:
@@ -52,7 +57,11 @@ func Config(ctx context.Context, args []string, out io.Writer) error {
// ConfigValidate validates one fully resolved effective pipeline without
// loading session state or constructing runtime collaborators.
func ConfigValidate(_ context.Context, args []string, out io.Writer) error {
func ConfigValidate(ctx context.Context, args []string, out io.Writer) error {
return configValidateWithDependencies(ctx, args, out, commandDependencies{})
}
func configValidateWithDependencies(_ context.Context, args []string, out io.Writer, deps commandDependencies) error {
flags, err := parseInspectionFlags("config validate", args, out)
if err != nil {
if errors.Is(err, flag.ErrHelp) {
@@ -60,7 +69,7 @@ func ConfigValidate(_ context.Context, args []string, out io.Writer) error {
}
return err
}
resolved, err := resolveInspectionConfig(flags)
resolved, err := resolveInspectionConfigWithDependencies(flags, deps)
if err != nil {
return fmt.Errorf("config validate: %w", err)
}
@@ -71,7 +80,11 @@ func ConfigValidate(_ context.Context, args []string, out io.Writer) error {
// ConfigShow validates and renders one fully resolved effective pipeline
// without loading session state or constructing runtime collaborators.
func ConfigShow(_ context.Context, args []string, out io.Writer) error {
func ConfigShow(ctx context.Context, args []string, out io.Writer) error {
return configShowWithDependencies(ctx, args, out, commandDependencies{})
}
func configShowWithDependencies(_ context.Context, args []string, out io.Writer, deps commandDependencies) error {
flags, err := parseInspectionFlags("config show", args, out)
if err != nil {
if errors.Is(err, flag.ErrHelp) {
@@ -79,7 +92,7 @@ func ConfigShow(_ context.Context, args []string, out io.Writer) error {
}
return err
}
resolved, err := resolveInspectionConfig(flags)
resolved, err := resolveInspectionConfigWithDependencies(flags, deps)
if err != nil {
return fmt.Errorf("config show: %w", err)
}
@@ -93,7 +106,11 @@ func ConfigShow(_ context.Context, args []string, out io.Writer) error {
// ConfigSources validates and reports deterministic effective configuration
// ownership without loading session state or runtime collaborators.
func ConfigSources(_ context.Context, args []string, out io.Writer) error {
func ConfigSources(ctx context.Context, args []string, out io.Writer) error {
return configSourcesWithDependencies(ctx, args, out, commandDependencies{})
}
func configSourcesWithDependencies(_ context.Context, args []string, out io.Writer, deps commandDependencies) error {
flags, err := parseInspectionFlags("config sources", args, out)
if err != nil {
if errors.Is(err, flag.ErrHelp) {
@@ -101,7 +118,7 @@ func ConfigSources(_ context.Context, args []string, out io.Writer) error {
}
return err
}
resolved, err := resolveInspectionConfig(flags)
resolved, err := resolveInspectionConfigWithDependencies(flags, deps)
if err != nil {
return fmt.Errorf("config sources: %w", err)
}
@@ -150,8 +167,8 @@ func parseInspectionFlags(command string, args []string, out io.Writer) (inspect
return flags, nil
}
func resolveInspectionConfig(flags inspectionFlags) (*inspectionConfig, error) {
pipelinePath, pipeline, err := loadPipelineConfig(flags.pipelinePath, config.PipelineLoadOptions{Profile: flags.profile.pointer()})
func resolveInspectionConfigWithDependencies(flags inspectionFlags, deps commandDependencies) (*inspectionConfig, error) {
pipelinePath, pipeline, err := loadPipelineConfigWithDependencies(flags.pipelinePath, config.PipelineLoadOptions{Profile: flags.profile.pointer()}, deps)
if err != nil {
return nil, err
}

View File

@@ -47,6 +47,38 @@ func TestConfigCommandHelpAndDispatch(t *testing.T) {
}
}
func TestExecuteConfigUsesInvocationPipelineLoader(t *testing.T) {
dir := t.TempDir()
pipelinePath := filepath.Join(dir, "pipeline.yml")
mustWriteTestFile(t, pipelinePath, "workspace:\n root: "+filepath.Join(dir, "workspace")+"\nwhisperx:\n transcribe_url: https://transcription.example.com/transcribe\n")
for _, subcommand := range []string{"validate", "show", "sources"} {
t.Run(subcommand, func(t *testing.T) {
calls := 0
deps := commandDependencies{
loadPipelineConfig: func(path string, opts config.PipelineLoadOptions) (*config.PipelineConfig, error) {
calls++
return config.LoadPipelineWithOptions(path, opts)
},
}
var stdout, stderr bytes.Buffer
code := executeWithDependencies(
[]string{"config", subcommand, "--config", pipelinePath},
&stdout,
&stderr,
deps,
executePlan,
)
if code != 0 {
t.Fatalf("exit code = %d, want 0; stdout=%q stderr=%q", code, stdout.String(), stderr.String())
}
if calls != 1 {
t.Fatalf("pipeline loader calls = %d, want 1", calls)
}
})
}
}
func TestConfigValidateAndShowPipelineOnlyAreSideEffectFree(t *testing.T) {
dir := t.TempDir()
workspaceRoot := filepath.Join(dir, "workspace-does-not-exist")