gitdataai/apps/migrate/src/main.rs
2026-04-14 19:02:01 +08:00

103 lines
3.2 KiB
Rust

use anyhow::Context;
use clap::Command;
use migrate::MigratorTrait;
use sea_orm::{Database, DatabaseConnection};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
config::AppConfig::load();
let cmd = Command::new("migrate")
.about("Database migration CLI")
.arg(
clap::Arg::new("steps")
.help("Number of migrations (for up/down)")
.required(false)
.index(1),
)
.subcommand(Command::new("up").about("Apply pending migrations"))
.subcommand(Command::new("down").about("Revert applied migrations"))
.subcommand(Command::new("fresh").about("Drop all tables and re-apply"))
.subcommand(Command::new("refresh").about("Revert all then re-apply"))
.subcommand(Command::new("reset").about("Revert all applied migrations"))
.subcommand(Command::new("status").about("Show migration status"))
.try_get_matches()
.map_err(|e| anyhow::anyhow!("{}", e))?;
let db_url = config::AppConfig::load().database_url()?;
let db: DatabaseConnection = Database::connect(&db_url).await?;
match cmd.subcommand_name() {
Some("up") => {
let steps = cmd
.get_one::<String>("steps")
.and_then(|s| s.parse().ok())
.unwrap_or(0);
run_up(&db, steps).await?;
}
Some("down") => {
let steps = cmd
.get_one::<String>("steps")
.and_then(|s| s.parse().ok())
.unwrap_or(1);
run_down(&db, steps).await?;
}
Some("fresh") => run_fresh(&db).await?,
Some("refresh") => run_refresh(&db).await?,
Some("reset") => run_reset(&db).await?,
Some("status") => run_status(&db).await?,
_ => {
eprintln!(
"Usage: migrate <command>\nCommands: up, down, fresh, refresh, reset, status"
);
std::process::exit(1);
}
}
Ok(())
}
async fn run_up(db: &DatabaseConnection, steps: u32) -> anyhow::Result<()> {
migrate::Migrator::up(db, if steps == 0 { None } else { Some(steps) })
.await
.context("failed to run migrations up")?;
Ok(())
}
async fn run_down(db: &DatabaseConnection, steps: u32) -> anyhow::Result<()> {
migrate::Migrator::down(db, Some(steps))
.await
.context("failed to run migrations down")?;
Ok(())
}
async fn run_fresh(db: &DatabaseConnection) -> anyhow::Result<()> {
migrate::Migrator::fresh(db)
.await
.context("failed to run migrations fresh")?;
Ok(())
}
async fn run_refresh(db: &DatabaseConnection) -> anyhow::Result<()> {
migrate::Migrator::refresh(db)
.await
.context("failed to run migrations refresh")?;
Ok(())
}
async fn run_reset(db: &DatabaseConnection) -> anyhow::Result<()> {
migrate::Migrator::reset(db)
.await
.context("failed to run migrations reset")?;
Ok(())
}
async fn run_status(db: &DatabaseConnection) -> anyhow::Result<()> {
migrate::Migrator::status(db)
.await
.context("failed to get migration status")?;
Ok(())
}