Carry dependencies through config commands
This commit is contained in:
@@ -48,7 +48,7 @@ func executeWithDependencies(args []string, stdout, stderr io.Writer, deps comma
|
|||||||
case "clean":
|
case "clean":
|
||||||
err = cleanWithDependencies(ctx, cmdArgs, stdout, deps)
|
err = cleanWithDependencies(ctx, cmdArgs, stdout, deps)
|
||||||
case "config":
|
case "config":
|
||||||
err = Config(ctx, cmdArgs, stdout)
|
err = configWithDependencies(ctx, cmdArgs, stdout, deps)
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(stderr, "unknown command: %q\n\n", cmd)
|
fmt.Fprintf(stderr, "unknown command: %q\n\n", cmd)
|
||||||
printUsage(stderr)
|
printUsage(stderr)
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ type inspectionConfig struct {
|
|||||||
|
|
||||||
// Config dispatches read-only pipeline configuration commands.
|
// Config dispatches read-only pipeline configuration commands.
|
||||||
func Config(ctx context.Context, args []string, out io.Writer) error {
|
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 {
|
if len(args) == 0 {
|
||||||
return fmt.Errorf("config: expected subcommand: validate|show|sources|diff")
|
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] {
|
switch args[0] {
|
||||||
case "validate":
|
case "validate":
|
||||||
return ConfigValidate(ctx, args[1:], out)
|
return configValidateWithDependencies(ctx, args[1:], out, deps)
|
||||||
case "show":
|
case "show":
|
||||||
return ConfigShow(ctx, args[1:], out)
|
return configShowWithDependencies(ctx, args[1:], out, deps)
|
||||||
case "sources":
|
case "sources":
|
||||||
return ConfigSources(ctx, args[1:], out)
|
return configSourcesWithDependencies(ctx, args[1:], out, deps)
|
||||||
case "diff":
|
case "diff":
|
||||||
return ConfigDiff(ctx, args[1:], out)
|
return ConfigDiff(ctx, args[1:], out)
|
||||||
default:
|
default:
|
||||||
@@ -52,7 +57,11 @@ func Config(ctx context.Context, args []string, out io.Writer) error {
|
|||||||
|
|
||||||
// ConfigValidate validates one fully resolved effective pipeline without
|
// ConfigValidate validates one fully resolved effective pipeline without
|
||||||
// loading session state or constructing runtime collaborators.
|
// 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)
|
flags, err := parseInspectionFlags("config validate", args, out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, flag.ErrHelp) {
|
if errors.Is(err, flag.ErrHelp) {
|
||||||
@@ -60,7 +69,7 @@ func ConfigValidate(_ context.Context, args []string, out io.Writer) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resolved, err := resolveInspectionConfig(flags)
|
resolved, err := resolveInspectionConfigWithDependencies(flags, deps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("config validate: %w", err)
|
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
|
// ConfigShow validates and renders one fully resolved effective pipeline
|
||||||
// without loading session state or constructing runtime collaborators.
|
// 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)
|
flags, err := parseInspectionFlags("config show", args, out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, flag.ErrHelp) {
|
if errors.Is(err, flag.ErrHelp) {
|
||||||
@@ -79,7 +92,7 @@ func ConfigShow(_ context.Context, args []string, out io.Writer) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resolved, err := resolveInspectionConfig(flags)
|
resolved, err := resolveInspectionConfigWithDependencies(flags, deps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("config show: %w", err)
|
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
|
// ConfigSources validates and reports deterministic effective configuration
|
||||||
// ownership without loading session state or runtime collaborators.
|
// 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)
|
flags, err := parseInspectionFlags("config sources", args, out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, flag.ErrHelp) {
|
if errors.Is(err, flag.ErrHelp) {
|
||||||
@@ -101,7 +118,7 @@ func ConfigSources(_ context.Context, args []string, out io.Writer) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resolved, err := resolveInspectionConfig(flags)
|
resolved, err := resolveInspectionConfigWithDependencies(flags, deps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("config sources: %w", err)
|
return fmt.Errorf("config sources: %w", err)
|
||||||
}
|
}
|
||||||
@@ -150,8 +167,8 @@ func parseInspectionFlags(command string, args []string, out io.Writer) (inspect
|
|||||||
return flags, nil
|
return flags, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveInspectionConfig(flags inspectionFlags) (*inspectionConfig, error) {
|
func resolveInspectionConfigWithDependencies(flags inspectionFlags, deps commandDependencies) (*inspectionConfig, error) {
|
||||||
pipelinePath, pipeline, err := loadPipelineConfig(flags.pipelinePath, config.PipelineLoadOptions{Profile: flags.profile.pointer()})
|
pipelinePath, pipeline, err := loadPipelineConfigWithDependencies(flags.pipelinePath, config.PipelineLoadOptions{Profile: flags.profile.pointer()}, deps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
func TestConfigValidateAndShowPipelineOnlyAreSideEffectFree(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
workspaceRoot := filepath.Join(dir, "workspace-does-not-exist")
|
workspaceRoot := filepath.Join(dir, "workspace-does-not-exist")
|
||||||
|
|||||||
Reference in New Issue
Block a user