From 5ddd73ee20887bb7601034a190aa301c2ff08d4f Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Sat, 8 Feb 2025 12:21:46 -0800 Subject: [PATCH] CLI - Warn when using an unstable command (#2227) Co-authored-by: Zeke Foppa --- crates/cli/src/subcommands/call.rs | 8 ++++++-- crates/cli/src/subcommands/describe.rs | 9 +++++++-- crates/cli/src/subcommands/energy.rs | 8 ++++++-- crates/cli/src/subcommands/init.rs | 6 ++++-- crates/cli/src/subcommands/list.rs | 8 +++++++- crates/cli/src/subcommands/server.rs | 8 ++++++-- crates/cli/src/subcommands/sql.rs | 5 +++-- crates/cli/src/subcommands/subscribe.rs | 8 +++++++- crates/cli/src/util.rs | 2 ++ 9 files changed, 48 insertions(+), 14 deletions(-) diff --git a/crates/cli/src/subcommands/call.rs b/crates/cli/src/subcommands/call.rs index 335b514c7c..0bd8ad75e8 100644 --- a/crates/cli/src/subcommands/call.rs +++ b/crates/cli/src/subcommands/call.rs @@ -1,7 +1,7 @@ use crate::common_args; use crate::config::Config; use crate::edit_distance::{edit_distance, find_best_match_for_name}; -use crate::util; +use crate::util::{self, UNSTABLE_WARNING}; use crate::util::{add_auth_header_opt, database_identity, get_auth_header}; use anyhow::{bail, Context, Error}; use clap::{Arg, ArgMatches}; @@ -16,7 +16,10 @@ use std::iter; pub fn cli() -> clap::Command { clap::Command::new("call") - .about("Invokes a reducer function in a database") + .about(format!( + "Invokes a reducer function in a database.\n\n{}", + UNSTABLE_WARNING + )) .arg( Arg::new("database") .required(true) @@ -35,6 +38,7 @@ pub fn cli() -> clap::Command { } pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), Error> { + eprintln!("{}\n", UNSTABLE_WARNING); let database = args.get_one::("database").unwrap(); let reducer_name = args.get_one::("reducer_name").unwrap(); let arguments = args.get_many::("arguments"); diff --git a/crates/cli/src/subcommands/describe.rs b/crates/cli/src/subcommands/describe.rs index 0cf6a7f2a3..6d8650efc6 100644 --- a/crates/cli/src/subcommands/describe.rs +++ b/crates/cli/src/subcommands/describe.rs @@ -1,11 +1,14 @@ use crate::common_args; use crate::config::Config; -use crate::util::{add_auth_header_opt, database_identity, get_auth_header}; +use crate::util::{add_auth_header_opt, database_identity, get_auth_header, UNSTABLE_WARNING}; use clap::{Arg, ArgMatches}; pub fn cli() -> clap::Command { clap::Command::new("describe") - .about("Describe the structure of a database or entities within it") + .about(format!( + "Describe the structure of a database or entities within it.\n\n{}", + UNSTABLE_WARNING + )) .arg( Arg::new("database") .required(true) @@ -28,6 +31,8 @@ pub fn cli() -> clap::Command { } pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> { + eprintln!("{}\n", UNSTABLE_WARNING); + let database = args.get_one::("database").unwrap(); let entity_name = args.get_one::("entity_name"); let entity_type = args.get_one::("entity_type"); diff --git a/crates/cli/src/subcommands/energy.rs b/crates/cli/src/subcommands/energy.rs index 555b4e7a5a..59b2cf528c 100644 --- a/crates/cli/src/subcommands/energy.rs +++ b/crates/cli/src/subcommands/energy.rs @@ -3,11 +3,14 @@ use crate::common_args; use clap::ArgMatches; use crate::config::Config; -use crate::util::{self, get_login_token_or_log_in}; +use crate::util::{self, get_login_token_or_log_in, UNSTABLE_WARNING}; pub fn cli() -> clap::Command { clap::Command::new("energy") - .about("Invokes commands related to database budgets") + .about(format!( + "Invokes commands related to database budgets.\n\n{}", + UNSTABLE_WARNING + )) .args_conflicts_with_subcommands(true) .subcommand_required(true) .subcommands(get_energy_subcommands()) @@ -39,6 +42,7 @@ async fn exec_subcommand(config: Config, cmd: &str, args: &ArgMatches) -> Result pub async fn exec(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> { let (cmd, subcommand_args) = args.subcommand().expect("Subcommand required"); + eprintln!("{}\n", UNSTABLE_WARNING); exec_subcommand(config, cmd, subcommand_args).await } diff --git a/crates/cli/src/subcommands/init.rs b/crates/cli/src/subcommands/init.rs index e018c3849a..48f14c2a69 100644 --- a/crates/cli/src/subcommands/init.rs +++ b/crates/cli/src/subcommands/init.rs @@ -1,6 +1,6 @@ -use crate::detect::find_executable; use crate::util::ModuleLanguage; use crate::Config; +use crate::{detect::find_executable, util::UNSTABLE_WARNING}; use anyhow::Context; use clap::{Arg, ArgMatches}; use colored::Colorize; @@ -8,7 +8,7 @@ use std::path::{Path, PathBuf}; pub fn cli() -> clap::Command { clap::Command::new("init") - .about("Initializes a new spacetime project") + .about(format!("Initializes a new spacetime project.\n\n{}", UNSTABLE_WARNING)) .arg( Arg::new("project-path") .value_parser(clap::value_parser!(PathBuf)) @@ -114,6 +114,8 @@ fn check_for_git() -> bool { } pub async fn exec(_config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> { + eprintln!("{}\n", UNSTABLE_WARNING); + let project_path = args.get_one::("project-path").unwrap(); let project_lang = *args.get_one::("lang").unwrap(); diff --git a/crates/cli/src/subcommands/list.rs b/crates/cli/src/subcommands/list.rs index 861e05de33..aacb9f3e23 100644 --- a/crates/cli/src/subcommands/list.rs +++ b/crates/cli/src/subcommands/list.rs @@ -1,6 +1,7 @@ use crate::common_args; use crate::util; use crate::util::get_login_token_or_log_in; +use crate::util::UNSTABLE_WARNING; use crate::Config; use clap::{ArgMatches, Command}; use reqwest::StatusCode; @@ -13,7 +14,10 @@ use tabled::{ pub fn cli() -> Command { Command::new("list") - .about("Lists the databases attached to an identity") + .about(format!( + "Lists the databases attached to an identity.\n\n{}", + UNSTABLE_WARNING + )) .arg(common_args::server().help("The nickname, host name or URL of the server from which to list databases")) .arg(common_args::yes()) } @@ -30,6 +34,8 @@ struct IdentityRow { } pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> { + eprintln!("{}\n", UNSTABLE_WARNING); + let server = args.get_one::("server").map(|s| s.as_ref()); let force = args.get_flag("force"); let token = get_login_token_or_log_in(&mut config, server, !force).await?; diff --git a/crates/cli/src/subcommands/server.rs b/crates/cli/src/subcommands/server.rs index c50e47b2b9..be1af47312 100644 --- a/crates/cli/src/subcommands/server.rs +++ b/crates/cli/src/subcommands/server.rs @@ -1,6 +1,6 @@ use crate::{ common_args, - util::{host_or_url_to_host_and_protocol, spacetime_server_fingerprint, y_or_n, VALID_PROTOCOLS}, + util::{host_or_url_to_host_and_protocol, spacetime_server_fingerprint, y_or_n, UNSTABLE_WARNING, VALID_PROTOCOLS}, Config, }; use anyhow::Context; @@ -16,7 +16,10 @@ pub fn cli() -> Command { .args_conflicts_with_subcommands(true) .subcommand_required(true) .subcommands(get_subcommands()) - .about("Manage the connection to the SpacetimeDB server") + .about(format!( + "Manage the connection to the SpacetimeDB server.\n\n{}", + UNSTABLE_WARNING + )) } fn get_subcommands() -> Vec { @@ -113,6 +116,7 @@ fn get_subcommands() -> Vec { pub async fn exec(config: Config, paths: &SpacetimePaths, args: &ArgMatches) -> Result<(), anyhow::Error> { let (cmd, subcommand_args) = args.subcommand().expect("Subcommand required"); + eprintln!("{}\n", UNSTABLE_WARNING); exec_subcommand(config, paths, cmd, subcommand_args).await } diff --git a/crates/cli/src/subcommands/sql.rs b/crates/cli/src/subcommands/sql.rs index aa11285f7e..6c546c0e9e 100644 --- a/crates/cli/src/subcommands/sql.rs +++ b/crates/cli/src/subcommands/sql.rs @@ -11,11 +11,11 @@ use tabled::settings::Style; use crate::config::Config; use crate::errors::error_for_status; -use crate::util::{database_identity, get_auth_header}; +use crate::util::{database_identity, get_auth_header, UNSTABLE_WARNING}; pub fn cli() -> clap::Command { clap::Command::new("sql") - .about("Runs a SQL query on the database.") + .about(format!("Runs a SQL query on the database.\n\n{}", UNSTABLE_WARNING)) .arg( Arg::new("database") .required(true) @@ -130,6 +130,7 @@ fn stmt_result_to_table(stmt_result: &StmtResultJson) -> anyhow::Result Result<(), anyhow::Error> { + eprintln!("{}\n", UNSTABLE_WARNING); let interactive = args.get_one::("interactive").unwrap_or(&false); if *interactive { let con = parse_req(config, args).await?; diff --git a/crates/cli/src/subcommands/subscribe.rs b/crates/cli/src/subcommands/subscribe.rs index a3070e65dd..4b47adf596 100644 --- a/crates/cli/src/subcommands/subscribe.rs +++ b/crates/cli/src/subcommands/subscribe.rs @@ -17,11 +17,15 @@ use tokio_tungstenite::tungstenite::Message as WsMessage; use crate::api::ClientApi; use crate::common_args; use crate::sql::parse_req; +use crate::util::UNSTABLE_WARNING; use crate::Config; pub fn cli() -> clap::Command { clap::Command::new("subscribe") - .about("Subscribe to SQL queries on the database.") + .about(format!( + "Subscribe to SQL queries on the database.\n\n{}", + UNSTABLE_WARNING + )) .arg( Arg::new("database") .required(true) @@ -121,6 +125,8 @@ struct SubscriptionTable { } pub async fn exec(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> { + eprintln!("{}\n", UNSTABLE_WARNING); + let queries = args.get_many::("query").unwrap(); let num = args.get_one::("num-updates").copied(); let timeout = args.get_one::("timeout").copied(); diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index d409d13921..8885b2aa33 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -15,6 +15,8 @@ use std::path::Path; use crate::config::Config; use crate::login::{spacetimedb_login_force, DEFAULT_AUTH_HOST}; +pub const UNSTABLE_WARNING: &str = "WARNING: This command is UNSTABLE and subject to breaking changes."; + /// Determine the identity of the `database`. pub async fn database_identity( config: &Config,