Skip to content

blue setup exits on an unreachable Control API URL instead of letting you re-enter it #90

Description

@cubeorgdev

What happened

During blue setup, the Control API URL prompt only re-prompts for syntactic problems. A
well-formed but wrong URL passes the prompt's .validate() closure, then fails at the discovery
step, and the whole command exits with status 1. Typo the hostname or pick the wrong deployment
and you have to re-run blue setup from the top instead of just correcting the URL.

Expected: a failed discovery should report the error and let me enter a different URL (with an
explicit way to cancel out), the way malformed input already does.

Steps to reproduce

  1. blue setup
  2. At Control API URL, enter a well-formed HTTPS URL that isn't a Blue deployment — e.g.
    https://harnes.example.com (typo'd host) or a host with no /.well-known/metaharness.
  3. The Discovering deployment… spinner fails, the error prints, and the process exits 1.
  4. There is no way to retry without starting blue setup over.

Where it happens

  • crates/gh-cli/src/commands.rs:79-96prompt_control_api_url(). The .validate() closure
    (:89) calls gh_service::validate_deployment_url, which only checks parse/host/HTTPS/no
    credentials-query-fragment (crates/gh-service/src/discovery.rs:29-50). Those failures do
    re-prompt correctly.
  • crates/gh-cli/src/commands.rs:98-117discover_configuration() runs after the prompt has
    returned and bubbles the error up.
  • crates/gh-service/src/discovery.rs:52-76discover() errors on DNS/TLS/timeout (:64),
    non-2xx (:65-70), invalid JSON (:71-73), and invalid discovery document
    (validate_document, :78-101).
  • Call sites that die: commands.rs:302 (setup()) and commands.rs:729 (first-run path in
    start(), i.e. bare blue with no blue.toml).
  • Exit: crates/gh-cli/src/main.rs:177-180print_error(&e); std::process::exit(1).

Suggested fix

Wrap prompt + discovery in a retry loop used by both call sites (commands.rs:302 and
commands.rs:729): on discovery failure, show the error via cliclack::log::error, then re-prompt
for a different URL — either directly or gated on a cliclack::confirm("Try a different URL?"),
mirroring retry_gateway_setup (commands.rs:1100-1124). Declining should outro_cancel and exit
the way the existing cancel paths do (commands.rs:380-383). Keep the non-TTY bail! guard at
commands.rs:80-84 so automation still fails fast on the first error, and consider capping retries.

There is also an in-repo precedent for the loop shape itself at commands.rs:3254-3283
(loop { … cliclack::select … }, re-prompt until valid or cancel).

Blue version

main @ e596c5d

OS / environment

Any (logic is platform-independent; observed reading the source).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions