feat(pg-migration): variable providing for migrations
This commit is contained in:
@@ -44,6 +44,13 @@ fn run_app() -> Result<(), i32> {
|
|||||||
.env("PG_URL")
|
.env("PG_URL")
|
||||||
.required(true)
|
.required(true)
|
||||||
.num_args(1),
|
.num_args(1),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("set")
|
||||||
|
.short('v')
|
||||||
|
.long("set")
|
||||||
|
.num_args(1..)
|
||||||
|
.help("Pass variable assignments to psql in the format key=value"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
@@ -83,10 +90,14 @@ fn run_app() -> Result<(), i32> {
|
|||||||
}
|
}
|
||||||
Some(("migrate", sub_m)) => {
|
Some(("migrate", sub_m)) => {
|
||||||
let db_url = matches.get_one::<String>("db_url").unwrap();
|
let db_url = matches.get_one::<String>("db_url").unwrap();
|
||||||
|
let set_vars: Vec<String> = sub_m
|
||||||
|
.get_many::<String>("set")
|
||||||
|
.map(|vals| vals.cloned().collect())
|
||||||
|
.unwrap_or_else(Vec::new);
|
||||||
let mut client = Client::connect(db_url, NoTls).expect("DB connection failed");
|
let mut client = Client::connect(db_url, NoTls).expect("DB connection failed");
|
||||||
init_db(&mut client, &inherits);
|
init_db(&mut client, &inherits);
|
||||||
let force = sub_m.get_flag("force");
|
let force = sub_m.get_flag("force");
|
||||||
apply_migrations(&mut client, migration_dir, db_url, force)
|
apply_migrations(&mut client, migration_dir, db_url, force, &set_vars)
|
||||||
}
|
}
|
||||||
Some(("fetch", _)) => {
|
Some(("fetch", _)) => {
|
||||||
let db_url = matches.get_one::<String>("db_url").unwrap();
|
let db_url = matches.get_one::<String>("db_url").unwrap();
|
||||||
@@ -110,7 +121,7 @@ fn check_psql_installed() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_migrations(client: &mut Client, migration_dir: &str, db_url: &str, force: bool) -> Result<(), i32> {
|
fn apply_migrations(client: &mut Client, migration_dir: &str, db_url: &str, force: bool, set_vars: &[String]) -> Result<(), i32> {
|
||||||
// Get the list of new migrations from disk
|
// Get the list of new migrations from disk
|
||||||
let mut fs_entries: Vec<_> = fs::read_dir(migration_dir)
|
let mut fs_entries: Vec<_> = fs::read_dir(migration_dir)
|
||||||
.expect("Reading migration directory failed")
|
.expect("Reading migration directory failed")
|
||||||
@@ -145,26 +156,30 @@ fn apply_migrations(client: &mut Client, migration_dir: &str, db_url: &str, forc
|
|||||||
}
|
}
|
||||||
|
|
||||||
for fs_mig in fs_migrations {
|
for fs_mig in fs_migrations {
|
||||||
// Skip if already applied
|
|
||||||
if db_migrations.contains(&fs_mig) {
|
if db_migrations.contains(&fs_mig) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = std::process::Command::new("psql")
|
let mut cmd = std::process::Command::new("psql");
|
||||||
.arg("-d")
|
cmd.arg("-d")
|
||||||
.arg(db_url)
|
.arg(db_url);
|
||||||
.arg("-f")
|
|
||||||
.arg(Path::new(migration_dir).join(&fs_mig).to_str().unwrap())
|
// Add provided set variables as -v key=value
|
||||||
.status()
|
for var in set_vars {
|
||||||
.expect("psql execution failed");
|
cmd.arg("-v").arg(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.arg("-f")
|
||||||
|
.arg(Path::new(migration_dir).join(&fs_mig).to_str().unwrap());
|
||||||
|
|
||||||
|
let status = cmd.status().expect("psql execution failed");
|
||||||
|
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
eprintln!("Migration failed: {}", fs_mig);
|
eprintln!("Migration failed: {}", fs_mig);
|
||||||
return Err(3);
|
return Err(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
client
|
client.execute("INSERT INTO hectic.migration (name) VALUES ($1)", &[&fs_mig])
|
||||||
.execute("INSERT INTO hectic.migration (name) VALUES ($1)", &[&fs_mig])
|
|
||||||
.expect("Recording migration failed");
|
.expect("Recording migration failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user