Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix exit codes of binaries #172

Merged
merged 5 commits into from
Jan 8, 2025
Merged
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use {{crate_name}}_web::test_helpers::{BodyExt, DbTestContext, RouterExt};
use axum::{
body::Body,
http::{self, Method},
Expand All @@ -8,6 +7,7 @@ use googletest::prelude::*;
use hyper::StatusCode;
use {{db_crate_name}}::{entities, transaction, Error};
use {{macros_crate_name}}::db_test;
use {{web_crate_name}}::test_helpers::{BodyExt, DbTestContext, RouterExt};
use serde_json::json;
use std::collections::HashMap;
use uuid::Uuid;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{%- if has_db -%}
use {{crate_name}}_web::test_helpers::{BodyExt, DbTestContext, RouterExt};
{% else %}
use {{crate_name}}_web::test_helpers::{BodyExt, DbTestContext, RouterExt};
{%- endif -%}
use axum::{body::Body, http::Method};
use googletest::prelude::*;
use hyper::StatusCode;
use {{macros_crate_name}}::test;
{% if has_db -%}
use {{web_crate_name}}::test_helpers::{BodyExt, DbTestContext, RouterExt};
{% else %}
use {{web_crate_name}}::test_helpers::{BodyExt, TestContext, RouterExt};
{%- endif -%}
use std::collections::HashMap;

#[db_test]
Expand Down
192 changes: 91 additions & 101 deletions blueprint/cli/src/bin/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,27 @@ use sqlx::{
ConnectOptions, Connection, Executor,
};
use tokio::io::{stdin, AsyncBufReadExt};

use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Stdio;
use std::process::{ExitCode, Stdio};
use url::Url;

#[tokio::main]
async fn main() {
cli().await;
async fn main() -> ExitCode {
let mut stdout = std::io::stdout();
let mut stderr = std::io::stderr();

let args = Cli::parse();
let mut ui = UI::new(&mut stdout, &mut stderr, !args.no_color, !args.quiet);

match cli(&mut ui, args).await {
Ok(_) => ExitCode::SUCCESS,
Err(e) => {
ui.error(e.to_string().as_str(), &e);
ExitCode::FAILURE
}
}
}

#[derive(Parser)]
Expand Down Expand Up @@ -56,114 +67,93 @@ enum Commands {
}

#[allow(missing_docs)]
async fn cli() {
let cli = Cli::parse();

let mut stdout = std::io::stdout();
let mut stderr = std::io::stderr();
let mut ui = UI::new(&mut stdout, &mut stderr, !cli.no_color, !cli.quiet);

async fn cli(mut ui: &mut UI<'_>, cli: Cli) -> Result<(), anyhow::Error> {
let config: Result<Config, anyhow::Error> = load_config(&cli.env);
match config {
Ok(config) => match cli.command {
Commands::Drop => {
ui.info(&format!("Dropping {} database…", &cli.env));
match drop(&config.database).await {
Ok(db_name) => {
ui.success(&format!("Dropped database {} successfully.", &db_name))
}
Err(e) => ui.error("Could not drop database!", e),
Ok(config) => {
match cli.command {
Commands::Drop => {
ui.info(&format!("Dropping {} database…", &cli.env));
let db_name = drop(&config.database)
.await
.context("Could not drop database!")?;
ui.success(&format!("Dropped database {} successfully.", db_name));
Ok(())
}
}
Commands::Create => {
ui.info(&format!("Creating {} database…", &cli.env));
match create(&config.database).await {
Ok(db_name) => {
ui.success(&format!("Created database {} successfully.", &db_name))
}
Err(e) => ui.error("Could not create database!", e),
Commands::Create => {
ui.info(&format!("Creating {} database…", &cli.env));
let db_name = create(&config.database)
.await
.context("Could not create database!")?;
ui.success(&format!("Created database {} successfully.", db_name));
Ok(())
}
}
Commands::Migrate => {
ui.info(&format!("Migrating {} database…", &cli.env));
ui.indent();
match migrate(&mut ui, &config.database).await {
Ok(migrations) => {
ui.outdent();
ui.success(&format!("{} migrations applied.", migrations));
}
Err(e) => {
ui.outdent();
ui.error("Could not migrate database!", e);
}
Commands::Migrate => {
ui.info(&format!("Migrating {} database…", &cli.env));
ui.indent();
marcoow marked this conversation as resolved.
Show resolved Hide resolved
let migrations = migrate(&mut ui, &config.database)
.await
.context("Could not migrate database!");
ui.outdent();
let migrations = migrations?;
ui.success(&format!("{} migrations applied.", migrations));
Ok(())
}
}
Commands::Seed => {
ui.info(&format!("Seeding {} database…", &cli.env));
match seed(&config.database).await {
Ok(_) => ui.success("Seeded database successfully."),
Err(e) => ui.error("Could not seed database!", e),
}
}
Commands::Reset => {
ui.info(&format!("Resetting {} database…", &cli.env));
ui.indent();
match reset(&mut ui, &config.database).await {
Ok(db_name) => {
ui.outdent();
ui.success(&format!("Reset database {} successfully.", db_name));
}
Err(e) => {
ui.outdent();
ui.error("Could not reset database!", e)
}
Commands::Seed => {
ui.info(&format!("Seeding {} database…", &cli.env));
seed(&config.database)
.await
.context("Could not seed database!")?;
ui.success("Seeded database successfully.");
Ok(())
}
}
Commands::Prepare => {
if let Err(e) = ensure_sqlx_cli_installed(&mut ui).await {
ui.error("Error ensuring sqlx-cli is installed!", e);
return;
Commands::Reset => {
ui.info(&format!("Resetting {} database…", &cli.env));
ui.indent();
let result = reset(&mut ui, &config.database)
.await
.context("Could not reset the database!");
ui.outdent();
let db_name = result?;
ui.success(&format!("Reset database {} successfully.", db_name));
Ok(())
}

let cargo = get_cargo_path().expect("Existence of CARGO env var is asserted by calling `ensure_sqlx_cli_installed`");

let mut sqlx_prepare_command = {
let mut cmd = tokio::process::Command::new(&cargo);

cmd.args(["sqlx", "prepare", "--", "--all-targets", "--all-features"]);

let cmd_cwd = match db_package_root() {
Ok(cwd) => cwd,
Err(e) => {
ui.error("Error finding the root of the db package", e);
return;
}
Commands::Prepare => {
if let Err(e) = ensure_sqlx_cli_installed(&mut ui).await {
return Err(e.context("Error ensuring sqlx-cli is installed!"));
}

let cargo = get_cargo_path().expect("Existence of CARGO env var is asserted by calling `ensure_sqlx_cli_installed`");

let mut sqlx_prepare_command = {
let mut cmd = tokio::process::Command::new(&cargo);

cmd.args(["sqlx", "prepare", "--", "--all-targets", "--all-features"]);

let cmd_cwd = db_package_root().context("Error finding the root of the db package!")?;
cmd.current_dir(cmd_cwd);

cmd.env("DATABASE_URL", &config.database.url);
cmd
};
cmd.current_dir(cmd_cwd);

cmd.env("DATABASE_URL", &config.database.url);
cmd
};

let o = match sqlx_prepare_command.output().await {
Ok(o) => o,
Err(e) => {
ui.error(&format!("Could not run {cargo} sqlx prepare!"), e.into());
return;

let o = sqlx_prepare_command
.output()
.await
.context("Could not run {cargo} sqlx prepare!")?;
if !o.status.success() {
let error = anyhow!(String::from_utf8_lossy(&o.stdout).to_string()).context("Error generating query metadata. Are you sure the database is running and all migrations are applied?");
return Err(error);
}
};
if !o.status.success() {
ui.error(
"Error generating query metadata. Are you sure the database is running and all migrations are applied?",
anyhow!(String::from_utf8_lossy(&o.stdout).to_string()),
);
return;

ui.success("Query data written to db/.sqlx directory; please check this into version control.");
Ok(())
}

ui.success("Query data written to db/.sqlx directory; please check this into version control.");
}
},
Err(e) => ui.error("Could not load config!", e),
}
Err(e) => {
Err(e.context("Could not load config!"))
}
}
}

Expand Down
Loading
Loading