From 5dadc0772fa1a2a4f824fcb30b6d939e3ecc8611 Mon Sep 17 00:00:00 2001 From: cyq <15000851237@163.com> Date: Mon, 25 May 2026 10:13:12 +0800 Subject: [PATCH] fix: add top-level show alias --- cmd/container-use/config.go | 181 +++++++++++++++++-------------- cmd/container-use/config_test.go | 52 +++++++++ 2 files changed, 150 insertions(+), 83 deletions(-) create mode 100644 cmd/container-use/config_test.go diff --git a/cmd/container-use/config.go b/cmd/container-use/config.go index bd37fafd..80cfb69b 100644 --- a/cmd/container-use/config.go +++ b/cmd/container-use/config.go @@ -28,6 +28,86 @@ func withConfig(cmd *cobra.Command, fn func(*environment.EnvironmentConfig) erro return fn(config) } +func runConfigShow(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + repo, err := repository.Open(ctx, ".") + if err != nil { + return fmt.Errorf("failed to open repository: %w", err) + } + + var config *environment.EnvironmentConfig + + // If no environment is specified, use the default configuration + if len(args) == 0 { + config = environment.DefaultConfig() + if err := config.Load(repo.SourcePath()); err != nil { + return fmt.Errorf("failed to load configuration: %w", err) + } + } else { + envID := args[0] + env, err := repo.Info(ctx, envID) + if err != nil { + return err + } + config = env.State.Config + } + + if ok, _ := cmd.Flags().GetBool("json"); ok { + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + return enc.Encode(config) + } + + tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + defer tw.Flush() + + fmt.Fprintf(tw, "Base Image:\t%s\n", config.BaseImage) + fmt.Fprintf(tw, "Workdir:\t%s\n", config.Workdir) + + if len(config.SetupCommands) > 0 { + fmt.Fprintf(tw, "Setup Commands:\t\n") + for i, cmd := range config.SetupCommands { + fmt.Fprintf(tw, " %d.\t%s\n", i+1, cmd) + } + } else { + fmt.Fprintf(tw, "Setup Commands:\t(none)\n") + } + + if len(config.InstallCommands) > 0 { + fmt.Fprintf(tw, "Install Commands:\t\n") + for i, cmd := range config.InstallCommands { + fmt.Fprintf(tw, " %d.\t%s\n", i+1, cmd) + } + } else { + fmt.Fprintf(tw, "Install Commands:\t(none)\n") + } + + envKeys := config.Env.Keys() + if len(envKeys) > 0 { + fmt.Fprintf(tw, "Environment Variables:\t\n") + for i, key := range envKeys { + value := config.Env.Get(key) + fmt.Fprintf(tw, " %d.\t%s=%s\n", i+1, key, value) + } + } else { + fmt.Fprintf(tw, "Environment Variables:\t(none)\n") + } + + secretKeys := config.Secrets.Keys() + if len(secretKeys) > 0 { + fmt.Fprintf(tw, "Secrets:\t\n") + for i, key := range secretKeys { + value := config.Secrets.Get(key) + fmt.Fprintf(tw, " %d.\t%s=%s\n", i+1, key, value) + } + } else { + fmt.Fprintf(tw, "Secrets:\t(none)\n") + } + + return nil +} + // Helper function for config update operations func updateConfig(cmd *cobra.Command, fn func(*environment.EnvironmentConfig) error) error { ctx := cmd.Context() @@ -59,10 +139,6 @@ var configCmd = &cobra.Command{ These settings are stored in .container-use/environment.json and apply to all new environments.`, } -func init() { - configShowCmd.Flags().Bool("json", false, "Dump the configuration in JSON") -} - var configShowCmd = &cobra.Command{ Use: "show []", Short: "Show environment configuration", @@ -73,89 +149,24 @@ With an environment argument, shows the configuration for that specific environm container-use config show # Show the configuration for a specific environment -container-use config show my-env -`, +container-use config show my-env`, Args: cobra.MaximumNArgs(1), ValidArgsFunction: suggestEnvironments, - RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - - repo, err := repository.Open(ctx, ".") - if err != nil { - return fmt.Errorf("failed to open repository: %w", err) - } - - var config *environment.EnvironmentConfig - - // If no environment is specified, use the default configuration - if len(args) == 0 { - config = environment.DefaultConfig() - if err := config.Load(repo.SourcePath()); err != nil { - return fmt.Errorf("failed to load configuration: %w", err) - } - } else { - envID := args[0] - env, err := repo.Info(ctx, envID) - if err != nil { - return err - } - config = env.State.Config - } - - if ok, _ := cmd.Flags().GetBool("json"); ok { - enc := json.NewEncoder(os.Stdout) - enc.SetIndent("", " ") - return enc.Encode(config) - } - - tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - defer tw.Flush() - - fmt.Fprintf(tw, "Base Image:\t%s\n", config.BaseImage) - fmt.Fprintf(tw, "Workdir:\t%s\n", config.Workdir) - - if len(config.SetupCommands) > 0 { - fmt.Fprintf(tw, "Setup Commands:\t\n") - for i, cmd := range config.SetupCommands { - fmt.Fprintf(tw, " %d.\t%s\n", i+1, cmd) - } - } else { - fmt.Fprintf(tw, "Setup Commands:\t(none)\n") - } - - if len(config.InstallCommands) > 0 { - fmt.Fprintf(tw, "Install Commands:\t\n") - for i, cmd := range config.InstallCommands { - fmt.Fprintf(tw, " %d.\t%s\n", i+1, cmd) - } - } else { - fmt.Fprintf(tw, "Install Commands:\t(none)\n") - } - - envKeys := config.Env.Keys() - if len(envKeys) > 0 { - fmt.Fprintf(tw, "Environment Variables:\t\n") - for i, key := range envKeys { - value := config.Env.Get(key) - fmt.Fprintf(tw, " %d.\t%s=%s\n", i+1, key, value) - } - } else { - fmt.Fprintf(tw, "Environment Variables:\t(none)\n") - } + RunE: runConfigShow, +} - secretKeys := config.Secrets.Keys() - if len(secretKeys) > 0 { - fmt.Fprintf(tw, "Secrets:\t\n") - for i, key := range secretKeys { - value := config.Secrets.Get(key) - fmt.Fprintf(tw, " %d.\t%s=%s\n", i+1, key, value) - } - } else { - fmt.Fprintf(tw, "Secrets:\t(none)\n") - } +var showCmd = &cobra.Command{ + Use: configShowCmd.Use, + Short: configShowCmd.Short, + Long: configShowCmd.Long, + Example: `# Show the default environment configuration +container-use show - return nil - }, +# Show the configuration for a specific environment +container-use show my-env`, + Args: configShowCmd.Args, + ValidArgsFunction: configShowCmd.ValidArgsFunction, + RunE: runConfigShow, } var configImportCmd = &cobra.Command{ @@ -557,6 +568,9 @@ var configSecretClearCmd = &cobra.Command{ } func init() { + configShowCmd.Flags().Bool("json", false, "Dump the configuration in JSON") + showCmd.Flags().Bool("json", false, "Dump the configuration in JSON") + // Add base-image commands configBaseImageCmd.AddCommand(configBaseImageSetCmd) configBaseImageCmd.AddCommand(configBaseImageGetCmd) @@ -599,5 +613,6 @@ func init() { configCmd.AddCommand(agent.AgentCmd) // Add config command to root + rootCmd.AddCommand(showCmd) rootCmd.AddCommand(configCmd) } diff --git a/cmd/container-use/config_test.go b/cmd/container-use/config_test.go new file mode 100644 index 00000000..2fe8434f --- /dev/null +++ b/cmd/container-use/config_test.go @@ -0,0 +1,52 @@ +package main + +import ( + "bytes" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestShowCommandIsTopLevelAliasForConfigShow(t *testing.T) { + showCmd, _, err := rootCmd.Find([]string{"show"}) + require.NoError(t, err) + + configShowCmd, _, err := rootCmd.Find([]string{"config", "show"}) + require.NoError(t, err) + require.NotNil(t, showCmd) + require.NotNil(t, configShowCmd) + + assert.Equal(t, "show", showCmd.Name()) + assert.Equal(t, configShowCmd.Use, showCmd.Use) + assert.Equal(t, configShowCmd.Short, showCmd.Short) + assert.Equal(t, configShowCmd.Long, showCmd.Long) + assert.Equal(t, `# Show the default environment configuration +container-use show + +# Show the configuration for a specific environment +container-use show my-env`, showCmd.Example) + assert.Equal(t, reflect.ValueOf(configShowCmd.RunE).Pointer(), reflect.ValueOf(showCmd.RunE).Pointer()) + assert.Equal(t, reflect.ValueOf(configShowCmd.Args).Pointer(), reflect.ValueOf(showCmd.Args).Pointer()) + assert.Equal(t, reflect.ValueOf(configShowCmd.ValidArgsFunction).Pointer(), reflect.ValueOf(showCmd.ValidArgsFunction).Pointer()) + assert.NotNil(t, configShowCmd.Flags().Lookup("json")) + assert.NotNil(t, showCmd.Flags().Lookup("json")) +} + +func TestShowCommandVisibleInRootHelp(t *testing.T) { + buf := new(bytes.Buffer) + oldOut := rootCmd.OutOrStdout() + oldErr := rootCmd.ErrOrStderr() + rootCmd.SetOut(buf) + rootCmd.SetErr(buf) + defer rootCmd.SetOut(oldOut) + defer rootCmd.SetErr(oldErr) + + err := rootCmd.Help() + require.NoError(t, err) + + output := buf.String() + assert.Contains(t, output, "show") + assert.Contains(t, output, "Show environment configuration") +}