Ameer Ghani 84f21e99ef
cli: add --target-version CLI flags for migrate run/revert (#2538)
* cli: add --target-version CLI flags for migrate run/revert

* cli: fix broken test

* cli: test harness for `sqlx migrate` along with --target-version tests

* cli: Fail if version supplied to run/revert is too old/new

After some discussion with my coworkers, we thought about the behavior a bit more:

The behavior is now that for a run, if the provided version is too old, the CLI
will return with failure rather than being a no-op. This gives feedback to the
operator instead of being quiet.

It is still valid to up/downgrade to the latest version, this will still be a no-op
to allow for idempotency.
2023-07-31 12:49:53 -07:00

94 lines
2.6 KiB
Rust

use assert_cmd::{assert::Assert, Command};
use sqlx::{migrate::Migrate, Connection, SqliteConnection};
use std::{
env::temp_dir,
fs::remove_file,
path::{Path, PathBuf},
};
pub struct TestDatabase {
file_path: PathBuf,
migrations: String,
}
impl TestDatabase {
pub fn new(name: &str, migrations: &str) -> Self {
let migrations_path = Path::new("tests").join(migrations);
let file_path = Path::new(&temp_dir()).join(format!("test-{}.db", name));
let ret = Self {
file_path,
migrations: String::from(migrations_path.to_str().unwrap()),
};
Command::cargo_bin("cargo-sqlx")
.unwrap()
.args([
"sqlx",
"database",
"create",
"--database-url",
&ret.connection_string(),
])
.assert()
.success();
ret
}
pub fn connection_string(&self) -> String {
format!("sqlite://{}", self.file_path.display())
}
pub fn run_migration(&self, revert: bool, version: Option<i64>, dry_run: bool) -> Assert {
let ver = match version {
Some(v) => v.to_string(),
None => String::from(""),
};
Command::cargo_bin("cargo-sqlx")
.unwrap()
.args(
[
vec![
"sqlx",
"migrate",
match revert {
true => "revert",
false => "run",
},
"--database-url",
&self.connection_string(),
"--source",
&self.migrations,
],
match version {
Some(_) => vec!["--target-version", &ver],
None => vec![],
},
match dry_run {
true => vec!["--dry-run"],
false => vec![],
},
]
.concat(),
)
.assert()
}
pub async fn applied_migrations(&self) -> Vec<i64> {
let mut conn = SqliteConnection::connect(&self.connection_string())
.await
.unwrap();
conn.list_applied_migrations()
.await
.unwrap()
.iter()
.map(|m| m.version)
.collect()
}
}
impl Drop for TestDatabase {
fn drop(&mut self) {
remove_file(&self.file_path).unwrap();
}
}