Skip to content

Dev/olivierdubo/issues autocomplete#193

Open
duboolivier wants to merge 7 commits into
mainfrom
dev/olivierdubo/issues_autocomplete
Open

Dev/olivierdubo/issues autocomplete#193
duboolivier wants to merge 7 commits into
mainfrom
dev/olivierdubo/issues_autocomplete

Conversation

@duboolivier

Copy link
Copy Markdown
Contributor

Description

Added shell autocompletion for the --cloud-project flag across all ovhcloud cloud subcommands. When pressing TAB after --cloud-project, the CLI queries the OVHcloud API and displays the list of available project IDs with their descriptions. A new ovhcloud completion install command automatically sets up completion in the user's shell (~/.bashrc or ~/.zshrc) without any manual configuration.

Fixes #xx (issue)

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Improvement (improvement of existing commands)
  • Breaking change (fix or feature that can break a current behavior)
  • Documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have commented my code
  • I ran go mod tidy
  • I have added tests that prove my fix is effective or that my feature works

Signed-off-by: olivier dubo <olivier.dubo@ovhcloud.com>
Signed-off-by: olivier dubo <olivier.dubo@ovhcloud.com>
@duboolivier duboolivier requested a review from a team as a code owner May 21, 2026 07:41
Comment thread internal/completion/completion.go Outdated
}

var projectIDs []string
if err := httpLib.Client.Get("/v1/cloud/project", &projectIDs); err != nil {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should directly use fetchExpandedArray and then iterate on the results

Comment thread internal/cmd/cloud_alerting.go Outdated
Short: "Manage billing alert configurations in the given cloud project",
}
alertingCmd.PersistentFlags().StringVar(&cloud.CloudProject, "cloud-project", "", "Cloud project ID")
alertingCmd.RegisterFlagCompletionFunc("cloud-project", completion.CloudProjects) //nolint:errcheck

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of adding this line in every file, I think we could iterate on the children of the root cloud command and assign the completion func to each of them

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds shell autocompletion support focused on improving UX for Public Cloud commands by completing --cloud-project values from the OVHcloud API, and introduces a ovhcloud completion install helper to persist completion setup in common shells.

Changes:

  • Add a new internal/completion package with an API-backed completion provider for --cloud-project.
  • Introduce a new top-level completion command (bash/zsh/fish/powershell) plus completion install.
  • Register --cloud-project flag completion across many ovhcloud cloud ... subcommands.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/completion/completion.go Implements API-backed completion suggestions for --cloud-project.
internal/cmd/completion.go Adds ovhcloud completion generation and completion install workflow.
internal/cmd/cloud_user.go Registers --cloud-project flag completion for cloud user.
internal/cmd/cloud_storage_swift.go Registers --cloud-project flag completion for cloud storage swift.
internal/cmd/cloud_storage_object.go Registers --cloud-project flag completion for cloud storage object.
internal/cmd/cloud_storage_file.go Registers --cloud-project flag completion for cloud storage file.
internal/cmd/cloud_storage_block.go Registers --cloud-project flag completion for cloud storage block.
internal/cmd/cloud_ssh_key.go Registers --cloud-project flag completion for cloud ssh-key.
internal/cmd/cloud_savings_plan.go Registers --cloud-project flag completion for cloud savings-plan.
internal/cmd/cloud_region.go Registers --cloud-project flag completion for cloud region.
internal/cmd/cloud_reference.go Registers --cloud-project flag completion for cloud reference.
internal/cmd/cloud_quota.go Registers --cloud-project flag completion for cloud quota.
internal/cmd/cloud_project.go Registers --cloud-project flag completion for cloud project.
internal/cmd/cloud_operation.go Registers --cloud-project flag completion for cloud operation.
internal/cmd/cloud_network.go Registers --cloud-project flag completion for cloud network.
internal/cmd/cloud_managed_registry.go Registers --cloud-project flag completion for cloud managed-registry.
internal/cmd/cloud_managed_rancher.go Registers --cloud-project flag completion for cloud managed-rancher.
internal/cmd/cloud_managed_kubernetes.go Registers --cloud-project flag completion for cloud managed-kubernetes.
internal/cmd/cloud_managed_database.go Registers --cloud-project flag completion for cloud managed-database.
internal/cmd/cloud_managed_analytics.go Registers --cloud-project flag completion for cloud managed-analytics.
internal/cmd/cloud_loadbalancer.go Registers --cloud-project flag completion for cloud loadbalancer.
internal/cmd/cloud_ip.go Registers --cloud-project flag completion for cloud ip.
internal/cmd/cloud_instance.go Registers --cloud-project flag completion for cloud instance.
internal/cmd/cloud_alerting.go Registers --cloud-project flag completion for cloud alerting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +29 to +39
var suggestions []string
for _, id := range projectIDs {
var project struct {
Description string `json:"description"`
}
if err := httpLib.Client.Get(fmt.Sprintf("/v1/cloud/project/%s", id), &project); err == nil && project.Description != "" {
suggestions = append(suggestions, id+"\t"+project.Description)
} else {
suggestions = append(suggestions, id)
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, we should cache the results to avoid making the call every time

Comment on lines +72 to +75
var rcFile string
var completionLine string
home, _ := os.UserHomeDir()

Comment on lines +68 to +106
func runCompletionInstall(_ *cobra.Command, _ []string) error {
shell := os.Getenv("SHELL")
shellName := filepath.Base(shell)

var rcFile string
var completionLine string
home, _ := os.UserHomeDir()

switch shellName {
case "bash":
rcFile = filepath.Join(home, ".bashrc")
completionLine = `eval "$(ovhcloud completion bash)"`
case "zsh":
rcFile = filepath.Join(home, ".zshrc")
completionLine = `eval "$(ovhcloud completion zsh)"`
case "fish":
configDir := os.Getenv("XDG_CONFIG_HOME")
if configDir == "" {
configDir = filepath.Join(home, ".config")
}
fishCompDir := filepath.Join(configDir, "fish", "completions")
if err := os.MkdirAll(fishCompDir, 0755); err != nil {
return fmt.Errorf("failed to create fish completions dir: %w", err)
}
destFile := filepath.Join(fishCompDir, "ovhcloud.fish")
f, err := os.Create(destFile)
if err != nil {
return fmt.Errorf("failed to create fish completion file: %w", err)
}
defer f.Close()
if err := rootCmd.GenFishCompletion(f, true); err != nil {
return fmt.Errorf("failed to write fish completion: %w", err)
}
fmt.Printf("✅ Fish completion installed to %s\n", destFile)
return nil
default:
return fmt.Errorf("unsupported shell %q — please run 'ovhcloud completion bash|zsh|fish|powershell' manually", shellName)
}

Comment on lines 7 to 11
import (
"github.com/ovh/ovhcloud-cli/internal/services/cloud"
"github.com/spf13/cobra"
"github.com/ovh/ovhcloud-cli/internal/completion"
)
Comment on lines +18 to +66
func init() {
completionCmd := &cobra.Command{
Use: "completion [bash|zsh|fish|powershell]",
Short: "Generate shell completion scripts",
Long: `Generate shell completion scripts for ovhcloud CLI.

To load completions in your current shell session:

bash:
source <(ovhcloud completion bash)

zsh:
source <(ovhcloud completion zsh)

fish:
ovhcloud completion fish | source

To make completions permanent, run:

ovhcloud completion install
`,
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
Args: cobra.MatchAll(cobra.MaximumNArgs(1), cobra.OnlyValidArgs),
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return cmd.Help()
}
switch args[0] {
case "bash":
return rootCmd.GenBashCompletion(os.Stdout)
case "zsh":
return rootCmd.GenZshCompletion(os.Stdout)
case "fish":
return rootCmd.GenFishCompletion(os.Stdout, true)
case "powershell":
return rootCmd.GenPowerShellCompletionWithDesc(os.Stdout)
}
return nil
},
}

completionCmd.AddCommand(&cobra.Command{
Use: "install",
Short: "Install shell completion permanently in your shell rc file",
RunE: runCompletionInstall,
})

rootCmd.AddCommand(completionCmd)
}
Signed-off-by: olivier dubo <olivier.dubo@ovhcloud.com>
Signed-off-by: olivier dubo <olivier.dubo@ovhcloud.com>
Signed-off-by: olivier dubo <olivier.dubo@ovhcloud.com>
Signed-off-by: olivier dubo <olivier.dubo@ovhcloud.com>
Signed-off-by: olivier dubo <olivier.dubo@ovhcloud.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants