mirror of https://github.com/buster-so/buster.git
makefile fix, test env fixes, auth
This commit is contained in:
parent
8e3c3e3400
commit
69faf4faf9
|
@ -64,9 +64,11 @@ jobs:
|
||||||
# Sensitive values from Secrets
|
# Sensitive values from Secrets
|
||||||
OPENAI_API_KEY: ${{ secrets.GH_ACTIONS_OPENAI_API_KEY }}
|
OPENAI_API_KEY: ${{ secrets.GH_ACTIONS_OPENAI_API_KEY }}
|
||||||
RESEND_API_KEY: ${{ secrets.GH_ACTIONS_RESEND_API_KEY }}
|
RESEND_API_KEY: ${{ secrets.GH_ACTIONS_RESEND_API_KEY }}
|
||||||
COHERE_API_KEY: ${{ secrets.GH_ACTIONS_COHERE_API_KEY }}
|
|
||||||
LLM_API_KEY: ${{ secrets.GH_ACTIONS_LLM_API_KEY }}
|
LLM_API_KEY: ${{ secrets.GH_ACTIONS_LLM_API_KEY }}
|
||||||
LLM_BASE_URL: ${{ secrets.GH_ACTIONS_LLM_BASE_URL }}
|
LLM_BASE_URL: ${{ secrets.GH_ACTIONS_LLM_BASE_URL }}
|
||||||
|
RERANK_API_KEY: ${{ secrets.GH_ACTIONS_COHERE_API_KEY }}
|
||||||
|
RERANK_MODEL: rerank-v3.5
|
||||||
|
RERANK_BASE_URL: https://api.cohere.com/v2/rerank
|
||||||
|
|
||||||
- name: Stop Supabase # Use the cleanup action
|
- name: Stop Supabase # Use the cleanup action
|
||||||
uses: ./.github/actions/stop-supabase
|
uses: ./.github/actions/stop-supabase
|
||||||
|
|
|
@ -58,7 +58,9 @@ jobs:
|
||||||
-e RUST_LOG='debug' \
|
-e RUST_LOG='debug' \
|
||||||
-e OPENAI_API_KEY='${{ secrets.GH_ACTIONS_OPENAI_API_KEY }}' \
|
-e OPENAI_API_KEY='${{ secrets.GH_ACTIONS_OPENAI_API_KEY }}' \
|
||||||
-e RESEND_API_KEY='${{ secrets.GH_ACTIONS_RESEND_API_KEY }}' \
|
-e RESEND_API_KEY='${{ secrets.GH_ACTIONS_RESEND_API_KEY }}' \
|
||||||
-e COHERE_API_KEY='${{ secrets.GH_ACTIONS_COHERE_API_KEY }}' \
|
-e RERANK_API_KEY='${{ secrets.GH_ACTIONS_COHERE_API_KEY }}' \
|
||||||
|
-e RERANK_MODEL='rerank-v3.5' \
|
||||||
|
-e RERANK_BASE_URL='https://api.cohere.com/v2/rerank' \
|
||||||
-e LLM_API_KEY='${{ secrets.GH_ACTIONS_LLM_API_KEY }}' \
|
-e LLM_API_KEY='${{ secrets.GH_ACTIONS_LLM_API_KEY }}' \
|
||||||
-e LLM_BASE_URL='${{ secrets.GH_ACTIONS_LLM_BASE_URL }}' \
|
-e LLM_BASE_URL='${{ secrets.GH_ACTIONS_LLM_BASE_URL }}' \
|
||||||
local-api-test:latest
|
local-api-test:latest
|
||||||
|
|
|
@ -93,7 +93,9 @@ jobs:
|
||||||
-e RUST_LOG='debug' \
|
-e RUST_LOG='debug' \
|
||||||
-e OPENAI_API_KEY='${{ secrets.GH_ACTIONS_OPENAI_API_KEY }}' \
|
-e OPENAI_API_KEY='${{ secrets.GH_ACTIONS_OPENAI_API_KEY }}' \
|
||||||
-e RESEND_API_KEY='${{ secrets.GH_ACTIONS_RESEND_API_KEY }}' \
|
-e RESEND_API_KEY='${{ secrets.GH_ACTIONS_RESEND_API_KEY }}' \
|
||||||
-e COHERE_API_KEY='${{ secrets.GH_ACTIONS_COHERE_API_KEY }}' \
|
-e RERANK_API_KEY='${{ secrets.GH_ACTIONS_COHERE_API_KEY }}' \
|
||||||
|
-e RERANK_MODEL='rerank-v3.5' \
|
||||||
|
-e RERANK_BASE_URL='https://api.cohere.com/v2/rerank' \
|
||||||
-e LLM_API_KEY='${{ secrets.GH_ACTIONS_LLM_API_KEY }}' \
|
-e LLM_API_KEY='${{ secrets.GH_ACTIONS_LLM_API_KEY }}' \
|
||||||
-e LLM_BASE_URL='${{ secrets.GH_ACTIONS_LLM_BASE_URL }}' \
|
-e LLM_BASE_URL='${{ secrets.GH_ACTIONS_LLM_BASE_URL }}' \
|
||||||
local-api-test:latest
|
local-api-test:latest
|
||||||
|
|
42
api/makefile
42
api/makefile
|
@ -1,26 +1,16 @@
|
||||||
dev:
|
dev:
|
||||||
@echo "Checking/Restarting Redis for dev target..."
|
docker stop buster-redis-make || true && \
|
||||||
@if ! docker ps -q -f name=buster-redis-make -f status=running > /dev/null; then \
|
docker rm buster-redis-make || true && \
|
||||||
echo "Redis container 'buster-redis-make' not running. Restarting it..."; \
|
docker run -d --name buster-redis-make -p 6379:6379 -v buster_redis_data:/data redis && \
|
||||||
docker stop buster-redis-make || true; \
|
supabase db reset || true && \
|
||||||
docker rm buster-redis-make || true; \
|
supabase start || true && \
|
||||||
(cd .. && docker run -d --name buster-redis-make -p 6379:6379 -v buster_redis_data:/data redis && cd api); \
|
supabase db reset || true && \
|
||||||
echo "Redis restarted."; \
|
|
||||||
else \
|
|
||||||
echo "Redis container 'buster-redis-make' already running."; \
|
|
||||||
fi
|
|
||||||
@echo "Ensuring Supabase is (re)started for dev target..."
|
|
||||||
supabase stop || true
|
|
||||||
@echo "Starting Supabase..."
|
|
||||||
supabase start
|
|
||||||
@echo "Supabase (re)started."
|
|
||||||
supabase db reset
|
|
||||||
export DATABASE_URL=postgres://postgres:postgres@127.0.0.1:54322/postgres && \
|
export DATABASE_URL=postgres://postgres:postgres@127.0.0.1:54322/postgres && \
|
||||||
diesel migration run && \
|
diesel migration run || true && \
|
||||||
PGPASSWORD=postgres psql -h 127.0.0.1 -p 54322 -d postgres -U postgres -f libs/database/setup.sql && \
|
PGPASSWORD=postgres psql -h 127.0.0.1 -p 54322 -d postgres -U postgres -f libs/database/setup.sql || true && \
|
||||||
PGPASSWORD=postgres psql -h 127.0.0.1 -p 54322 -d postgres -U postgres -f libs/database/seed.sql && \
|
PGPASSWORD=postgres psql -h 127.0.0.1 -p 54322 -d postgres -U postgres -f libs/database/seed.sql || true && \
|
||||||
export RUST_LOG=debug
|
export RUST_LOG=debug && \
|
||||||
export CARGO_INCREMENTAL=1
|
export CARGO_INCREMENTAL=1 && \
|
||||||
nice cargo watch -C server -x run
|
nice cargo watch -C server -x run
|
||||||
|
|
||||||
update-seed:
|
update-seed:
|
||||||
|
@ -39,16 +29,6 @@ stop:
|
||||||
supabase stop
|
supabase stop
|
||||||
|
|
||||||
fast:
|
fast:
|
||||||
@echo "Checking Redis for fast target..."
|
|
||||||
@if ! docker ps -q -f name=buster-redis-make -f status=running > /dev/null; then \
|
|
||||||
echo "Redis container 'buster-redis-make' not running. Starting it..."; \
|
|
||||||
docker stop buster-redis-make || true; \
|
|
||||||
docker rm buster-redis-make || true; \
|
|
||||||
(cd .. && docker run -d --name buster-redis-make -p 6379:6379 -v buster_redis_data:/data redis && cd api); \
|
|
||||||
echo "Redis started."; \
|
|
||||||
else \
|
|
||||||
echo "Redis container 'buster-redis-make' already running."; \
|
|
||||||
fi
|
|
||||||
export RUST_LOG=debug && \
|
export RUST_LOG=debug && \
|
||||||
export CARGO_INCREMENTAL=1 && \
|
export CARGO_INCREMENTAL=1 && \
|
||||||
nice cargo watch -C server -x run
|
nice cargo watch -C server -x run
|
|
@ -30,8 +30,8 @@ pub enum AuthError {
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(about = "Authenticate with Buster API")]
|
#[command(about = "Authenticate with Buster API")]
|
||||||
pub struct AuthArgs {
|
pub struct AuthArgs {
|
||||||
/// The Buster API host UL
|
/// The Buster API host URL
|
||||||
#[arg(long, env = "BUSTER_HOST")]
|
#[arg(long, env = "BUSTER_HOST", conflicts_with_all = &["local", "cloud"])]
|
||||||
pub host: Option<String>,
|
pub host: Option<String>,
|
||||||
|
|
||||||
/// Your Buster API key
|
/// Your Buster API key
|
||||||
|
@ -45,6 +45,14 @@ pub struct AuthArgs {
|
||||||
/// Clear saved credentials
|
/// Clear saved credentials
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub clear: bool,
|
pub clear: bool,
|
||||||
|
|
||||||
|
/// Use local buster instance (http://localhost:3001)
|
||||||
|
#[arg(long, help = "Use local buster instance (http://localhost:3001)", conflicts_with_all = &["host", "cloud"])]
|
||||||
|
pub local: bool,
|
||||||
|
|
||||||
|
/// Use cloud buster instance (https://api.buster.so)
|
||||||
|
#[arg(long, help = "Use cloud buster instance (https://api.buster.so)", conflicts_with_all = &["host", "local"])]
|
||||||
|
pub cloud: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Credentials Validation Trait ---
|
// --- Credentials Validation Trait ---
|
||||||
|
@ -157,57 +165,86 @@ async fn handle_clear_flag(clear: bool) -> Result<bool> {
|
||||||
/// Loads existing credentials or initializes default ones, handling overrides from args/env.
|
/// Loads existing credentials or initializes default ones, handling overrides from args/env.
|
||||||
/// Also prompts for overwrite confirmation if necessary.
|
/// Also prompts for overwrite confirmation if necessary.
|
||||||
async fn load_and_confirm_credentials(args: &AuthArgs) -> Result<Option<BusterCredentials>> {
|
async fn load_and_confirm_credentials(args: &AuthArgs) -> Result<Option<BusterCredentials>> {
|
||||||
let mut buster_creds = match get_buster_credentials().await {
|
// 1. Load credentials as they are from cache, or use pristine defaults if no cache.
|
||||||
Ok(creds) => creds,
|
let loaded_creds = match get_buster_credentials().await {
|
||||||
Err(_) => BusterCredentials {
|
Ok(creds) => creds, // These are the actual stored credentials
|
||||||
|
Err(_) => BusterCredentials { // These are pristine defaults if nothing is stored
|
||||||
url: DEFAULT_HOST.to_string(),
|
url: DEFAULT_HOST.to_string(),
|
||||||
api_key: String::new(),
|
api_key: String::new(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let existing_creds_present = !buster_creds.url.is_empty() && !buster_creds.api_key.is_empty();
|
|
||||||
|
|
||||||
// Apply args overrides early - host
|
// 2. Determine if meaningful credentials were found in the cache.
|
||||||
if let Some(host) = &args.host {
|
// "Meaningful" here means an API key was actually stored.
|
||||||
buster_creds.url = host.clone();
|
let meaningful_cached_creds_existed = !loaded_creds.api_key.is_empty();
|
||||||
}
|
|
||||||
// Apply args overrides early - api key
|
|
||||||
if let Some(api_key) = &args.api_key {
|
|
||||||
buster_creds.api_key = api_key.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
let host_provided = args.host.is_some();
|
// 3. Prepare the credentials that will be used, starting with cached/default values.
|
||||||
let api_key_provided = args.api_key.is_some();
|
// These will be modified by CLI args.
|
||||||
let fully_provided_via_args = host_provided && api_key_provided;
|
let mut effective_creds = loaded_creds.clone();
|
||||||
|
|
||||||
// Prompt for overwrite confirmation only if existing creds are present *and* not fully overridden by args
|
// 4. Determine if host and API key are being specified by CLI arguments.
|
||||||
if existing_creds_present && !fully_provided_via_args {
|
// `conflicts_with_all` ensures only one of `args.local`, `args.cloud`, or `args.host` is active.
|
||||||
|
let host_is_specified_by_cli_args = args.local || args.cloud || args.host.is_some();
|
||||||
|
let api_key_is_specified_by_cli_args = args.api_key.is_some();
|
||||||
|
|
||||||
|
// 5. Decide whether to prompt for overwrite.
|
||||||
|
// Prompt if meaningful cached credentials existed AND
|
||||||
|
// the user is NOT providing a full set of overriding credentials (both host and API key) via CLI args.
|
||||||
|
if meaningful_cached_creds_existed && !(host_is_specified_by_cli_args && api_key_is_specified_by_cli_args) {
|
||||||
let confirm = Confirm::new("Existing credentials found. Do you want to overwrite them?")
|
let confirm = Confirm::new("Existing credentials found. Do you want to overwrite them?")
|
||||||
.with_default(false)
|
.with_default(false)
|
||||||
.with_help_message("Select 'y' to proceed with entering new credentials, or 'n' to cancel.")
|
.with_help_message("Select 'y' to proceed with configuring credentials, or 'n' to cancel.")
|
||||||
.prompt()
|
.prompt()
|
||||||
.map_err(|e| AuthError::UserInputFailed(e.to_string()))?;
|
.map_err(|e| AuthError::UserInputFailed(e.to_string()))?;
|
||||||
|
|
||||||
if !confirm {
|
if !confirm {
|
||||||
println!("Authentication cancelled.");
|
println!("Authentication cancelled.");
|
||||||
return Ok(None); // Signal cancellation
|
return Ok(None); // User cancelled, so don't proceed.
|
||||||
}
|
}
|
||||||
// If confirmed, proceed with the potentially modified buster_creds
|
// If user confirms, `effective_creds` (which will have CLI args applied next) will be used.
|
||||||
|
}
|
||||||
|
// If no meaningful cached creds, or if user provided full CLI args, no prompt needed.
|
||||||
|
|
||||||
|
// 6. Apply CLI argument overrides to `effective_creds`.
|
||||||
|
if args.local {
|
||||||
|
effective_creds.url = "http://localhost:3001".to_string();
|
||||||
|
} else if args.cloud {
|
||||||
|
effective_creds.url = DEFAULT_HOST.to_string();
|
||||||
|
} else if let Some(host_arg) = &args.host {
|
||||||
|
effective_creds.url = host_arg.clone();
|
||||||
|
}
|
||||||
|
// If no host arg was provided by CLI (neither --local, --cloud, nor --host) AND
|
||||||
|
// the URL in effective_creds is currently empty (e.g., cache was empty and returned BusterCredentials with empty url),
|
||||||
|
// set it to the default. This ensures URL is not empty before `prompt_for_missing_credentials`
|
||||||
|
// if no host arg was given and cache didn't provide one.
|
||||||
|
else if effective_creds.url.is_empty() { // This case handles if get_buster_credentials somehow returned empty URL or initial default was empty.
|
||||||
|
effective_creds.url = DEFAULT_HOST.to_string();
|
||||||
|
}
|
||||||
|
// If get_buster_credentials returned a specific URL from cache, and no host args are given, it remains that specific URL.
|
||||||
|
// If get_buster_credentials returned the default URL (or cache was empty -> default), and no host args, it remains default.
|
||||||
|
|
||||||
|
if let Some(api_key_arg) = &args.api_key {
|
||||||
|
effective_creds.api_key = api_key_arg.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(buster_creds))
|
Ok(Some(effective_creds))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prompts the user interactively for missing host and API key information.
|
/// Prompts the user interactively for missing host and API key information.
|
||||||
async fn prompt_for_missing_credentials(
|
async fn prompt_for_missing_credentials(
|
||||||
creds: &mut BusterCredentials,
|
creds: &mut BusterCredentials,
|
||||||
args: &AuthArgs,
|
args: &AuthArgs,
|
||||||
existing_creds_present: bool, // Needed to adjust prompt text
|
api_key_is_currently_set: bool, // Reflects if API key is set in `creds` before this prompt
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let host_provided = args.host.is_some();
|
let host_provided = args.host.is_some();
|
||||||
let api_key_provided = args.api_key.is_some();
|
let api_key_provided = args.api_key.is_some();
|
||||||
|
|
||||||
// Prompt for URL if not provided via args and current URL is default or empty
|
// Prompt for URL if:
|
||||||
if !host_provided && (creds.url.is_empty() || creds.url == DEFAULT_HOST) {
|
// - Not using --local.
|
||||||
|
// - Not using --cloud.
|
||||||
|
// - Not using --host.
|
||||||
|
// - AND the current URL in `creds` (after cache/args) is still empty or the default.
|
||||||
|
if !args.local && !args.cloud && args.host.is_none() && (creds.url.is_empty() || creds.url == DEFAULT_HOST) {
|
||||||
let default_url_to_show = if creds.url.is_empty() { DEFAULT_HOST } else { &creds.url };
|
let default_url_to_show = if creds.url.is_empty() { DEFAULT_HOST } else { &creds.url };
|
||||||
let url_input = Text::new("Enter the URL of your Buster API")
|
let url_input = Text::new("Enter the URL of your Buster API")
|
||||||
.with_default(default_url_to_show)
|
.with_default(default_url_to_show)
|
||||||
|
@ -231,7 +268,7 @@ async fn prompt_for_missing_credentials(
|
||||||
format!("{}...", &creds.api_key[0..std::cmp::min(4, creds.api_key.len())])
|
format!("{}...", &creds.api_key[0..std::cmp::min(4, creds.api_key.len())])
|
||||||
};
|
};
|
||||||
|
|
||||||
let prompt_message = if existing_creds_present {
|
let prompt_message = if api_key_is_currently_set { // Use the passed flag
|
||||||
format!("Enter new API key (current: {obfuscated_api_key}):")
|
format!("Enter new API key (current: {obfuscated_api_key}):")
|
||||||
} else {
|
} else {
|
||||||
format!("Enter your API key (current: {obfuscated_api_key}):")
|
format!("Enter your API key (current: {obfuscated_api_key}):")
|
||||||
|
@ -271,13 +308,27 @@ async fn save_credentials_or_notify(
|
||||||
creds: BusterCredentials,
|
creds: BusterCredentials,
|
||||||
no_save: bool,
|
no_save: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if !no_save {
|
let masked_api_key = if creds.api_key.is_empty() {
|
||||||
set_buster_credentials(creds).await
|
"[Not Set]".to_string() // Should ideally not happen if validation passed
|
||||||
.map_err(|e| AuthError::SaveCredentialsFailed(e.to_string()))?;
|
|
||||||
println!("Credentials saved successfully!");
|
|
||||||
} else {
|
} else {
|
||||||
println!("Authentication successful!");
|
let api_key_len = creds.api_key.len();
|
||||||
println!("Note: Credentials were not saved due to --no-save flag");
|
let visible_part_start_index = if api_key_len > 6 { api_key_len - 6 } else { 0 };
|
||||||
|
format!("****{}", &creds.api_key[visible_part_start_index..])
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("✅ You've successfully connected to Buster!");
|
||||||
|
println!(); // Newline for separation
|
||||||
|
println!("Connection details:");
|
||||||
|
println!(" host: {}", creds.url);
|
||||||
|
println!(" api_key: {}", masked_api_key);
|
||||||
|
|
||||||
|
if !no_save {
|
||||||
|
set_buster_credentials(creds)
|
||||||
|
.await
|
||||||
|
.map_err(|e| AuthError::SaveCredentialsFailed(e.to_string()))?;
|
||||||
|
println!("\nCredentials saved successfully!");
|
||||||
|
} else {
|
||||||
|
println!("\nNote: Credentials were not saved due to --no-save flag");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -289,24 +340,43 @@ pub async fn auth_with_args(args: AuthArgs) -> Result<()> {
|
||||||
return Ok(()); // Exit early if credentials were cleared
|
return Ok(()); // Exit early if credentials were cleared
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Load existing credentials or initialize defaults, confirm overwrite if needed
|
// 2. Load existing credentials or initialize defaults, confirm overwrite if needed, and apply args
|
||||||
let mut opt_buster_creds = match load_and_confirm_credentials(&args).await? {
|
let mut creds_after_load_and_args = match load_and_confirm_credentials(&args).await? {
|
||||||
Some(creds) => creds,
|
Some(creds) => creds,
|
||||||
None => return Ok(()), // User cancelled overwrite prompt
|
None => return Ok(()), // User cancelled overwrite prompt
|
||||||
};
|
};
|
||||||
let existing_creds_present = !opt_buster_creds.url.is_empty() && !opt_buster_creds.api_key.is_empty();
|
|
||||||
|
|
||||||
|
// Store the host URL that will be used for connection attempts.
|
||||||
|
// This URL is determined after considering cache, defaults, and CLI args like --local, --cloud, --host.
|
||||||
|
let attempted_host_url = creds_after_load_and_args.url.clone();
|
||||||
|
|
||||||
|
// This flag is for tailoring the prompt text in `prompt_for_missing_credentials`.
|
||||||
|
let api_key_is_present_before_interactive_prompt = !creds_after_load_and_args.api_key.is_empty();
|
||||||
|
|
||||||
// 3. Prompt for missing credentials interactively
|
// 3. Prompt for missing credentials interactively
|
||||||
prompt_for_missing_credentials(&mut opt_buster_creds, &args, existing_creds_present).await?;
|
if let Err(prompt_err) = prompt_for_missing_credentials(
|
||||||
|
&mut creds_after_load_and_args,
|
||||||
|
&args,
|
||||||
|
api_key_is_present_before_interactive_prompt
|
||||||
|
).await {
|
||||||
|
eprintln!("Failed during credential input process.");
|
||||||
|
eprintln!("Intended host for configuration: {}", attempted_host_url);
|
||||||
|
return Err(prompt_err); // Propagate the original error (anyhow::Error)
|
||||||
|
}
|
||||||
|
|
||||||
// 4. Validate the final credentials
|
// 4. Validate the final credentials
|
||||||
let validator = RealCredentialsValidator;
|
let validator = RealCredentialsValidator;
|
||||||
validate_credentials(&opt_buster_creds, &validator).await?;
|
if let Err(validation_err) = validate_credentials(&creds_after_load_and_args, &validator).await {
|
||||||
|
// validation_err is AuthError. We print its specific message.
|
||||||
|
eprintln!("Authentication failed: {}", validation_err);
|
||||||
|
eprintln!("Attempted to connect to host: {}", attempted_host_url);
|
||||||
|
return Err(validation_err.into()); // Propagate as anyhow::Error
|
||||||
|
}
|
||||||
|
|
||||||
// 5. Save credentials or notify
|
// 5. Save credentials or notify
|
||||||
save_credentials_or_notify(opt_buster_creds, args.no_save).await?;
|
// This function prints connection details (including host) on success internally.
|
||||||
|
// If it errors, it's a save error after successful validation, not a connection/validation error.
|
||||||
|
save_credentials_or_notify(creds_after_load_and_args, args.no_save).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,14 @@ pub enum Commands {
|
||||||
/// Clear saved credentials
|
/// Clear saved credentials
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
clear: bool,
|
clear: bool,
|
||||||
|
|
||||||
|
/// Use local Buster API
|
||||||
|
#[arg(long)]
|
||||||
|
local: bool,
|
||||||
|
|
||||||
|
/// Use cloud Buster API
|
||||||
|
#[arg(long)]
|
||||||
|
cloud: bool,
|
||||||
},
|
},
|
||||||
/// Update buster-cli to the latest version
|
/// Update buster-cli to the latest version
|
||||||
Update {
|
Update {
|
||||||
|
@ -111,12 +119,16 @@ async fn main() {
|
||||||
api_key,
|
api_key,
|
||||||
no_save,
|
no_save,
|
||||||
clear,
|
clear,
|
||||||
|
local,
|
||||||
|
cloud,
|
||||||
} => {
|
} => {
|
||||||
commands::auth::auth_with_args(AuthArgs {
|
commands::auth::auth_with_args(AuthArgs {
|
||||||
host,
|
host,
|
||||||
api_key,
|
api_key,
|
||||||
no_save,
|
no_save,
|
||||||
clear,
|
clear,
|
||||||
|
local,
|
||||||
|
cloud,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue