Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-auth-setup-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@googleworkspace/cli": patch
---

fix: `gws auth setup --help` now prints usage instead of running the setup wizard
35 changes: 35 additions & 0 deletions src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,21 @@ fn prompt_login_after_setup() -> Result<bool, GwsError> {

/// Run the full setup flow. Orchestrates all steps and outputs JSON summary.
pub async fn run_setup(args: &[String]) -> Result<(), GwsError> {
// Early-return for --help/-h so we never start the wizard or check for gcloud.
if args.iter().any(|a| a == "--help" || a == "-h") {
println!(
"Usage: gws auth setup [options]\n\n\
Configure a GCP project, enable Workspace APIs, and create OAuth\n\
credentials — all in one guided wizard.\n\n\
Options:\n\
\x20 --project <ID> Use an existing GCP project instead of creating one\n\
\x20 --dry-run Show what would be done without making changes\n\
\x20 --login Run `gws auth login` after successful setup\n\
\x20 -h, --help Show this help message"
);
return Ok(());
}
Comment on lines +1602 to +1614
Copy link
Contributor

Choose a reason for hiding this comment

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

high

For better maintainability and readability, it's a good practice to extract string literals, especially multi-line ones, into constants. This makes the help text easier to find and modify without digging into the logic. While a module-level const would be ideal, defining it inside the if block is still a good improvement that can be applied within the scope of this diff.

    if args.iter().any(|a| a == "--help" || a == "-h") {
        const SETUP_USAGE: &str = "Usage: gws auth setup [options]\n\n\
             Configure a GCP project, enable Workspace APIs, and create OAuth\n\
             credentials — all in one guided wizard.\n\n\
             Options:\n\
             \x20 --project <ID>  Use an existing GCP project instead of creating one\n\
             \x20 --dry-run       Show what would be done without making changes\n\
             \x20 --login         Run `gws auth login` after successful setup\n\
             \x20 -h, --help      Show this help message";
        println!("{SETUP_USAGE}");
        return Ok(());
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Noted, but keeping the string inline here for simplicity — this is a small, self-contained usage block (8 lines) in a single function. Extracting it to a constant would add indirection without much benefit at this scale. Happy to refactor if the maintainer prefers it.


let opts = parse_setup_args(args);
let dry_run = opts.dry_run;
let interactive = std::io::IsTerminal::is_terminal(&std::io::stdin()) && !dry_run;
Expand Down Expand Up @@ -2312,4 +2327,24 @@ mod tests {
assert_eq!(bin, "gcloud");
}
}

#[tokio::test]
async fn run_setup_help_flag_returns_ok_without_starting_wizard() {
// --help should print usage and return Ok without requiring gcloud.
let result = run_setup(&["--help".to_string()]).await;
assert!(result.is_ok());
}

#[tokio::test]
async fn run_setup_short_help_flag_returns_ok() {
let result = run_setup(&["-h".to_string()]).await;
assert!(result.is_ok());
}

#[tokio::test]
async fn run_setup_help_with_other_args_returns_ok() {
// --help should take priority even when combined with other flags.
let result = run_setup(&["--project".to_string(), "my-proj".to_string(), "--help".to_string()]).await;
assert!(result.is_ok());
}
}
Loading