~vpzom/lotide

38ef280da222eb7a7b08380127f1078c785128ec — Colin Reeder 10 months ago a07ab6a
Embed migrations into build (#96)
5 files changed, 310 insertions(+), 19 deletions(-)

M Cargo.lock
M Cargo.toml
A build.rs
M src/main.rs
A src/migrate.rs
M Cargo.lock => Cargo.lock +165 -18
@@ 26,6 26,21 @@ dependencies = [
]

[[package]]
name = "addr2line"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
dependencies = [
 "gimli",
]

[[package]]
name = "adler"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"

[[package]]
name = "ahash"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 94,6 109,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"

[[package]]
name = "backtrace"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598"
dependencies = [
 "addr2line",
 "cfg-if 1.0.0",
 "libc",
 "miniz_oxide",
 "object",
 "rustc-demangle",
]

[[package]]
name = "base64"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 219,6 248,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "chrono"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 297,7 332,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "crossbeam-utils",
 "maybe-uninit",
]


@@ 309,7 344,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [
 "autocfg",
 "cfg-if",
 "cfg-if 0.1.10",
 "lazy_static",
]



@@ 330,7 365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f260e2fc850179ef410018660006951c1b55b79e8087e87111a2c388994b9b5"
dependencies = [
 "ahash",
 "cfg-if",
 "cfg-if 0.1.10",
 "num_cpus",
]



@@ 400,7 435,17 @@ version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
]

[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
 "backtrace",
 "version_check",
]

[[package]]


@@ 662,7 707,7 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "libc",
 "wasi",
]


@@ 673,12 718,18 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "libc",
 "wasi",
]

[[package]]
name = "gimli"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"

[[package]]
name = "h2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1003,7 1054,7 @@ checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
dependencies = [
 "arrayvec",
 "bitflags",
 "cfg-if",
 "cfg-if 0.1.10",
 "ryu",
 "static_assertions",
]


@@ 1029,7 1080,7 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
]

[[package]]


@@ 1038,7 1089,7 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ecc775857611e1df29abba5c41355cdf540e7e9d4acfdf0f355eefee82330b7"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "generator",
 "scoped-tls",
]


@@ 1071,6 1122,7 @@ dependencies = [
 "hyper-tls",
 "lazy_static",
 "lettre",
 "migrant_lib",
 "mime",
 "openssl",
 "pdcm-linkify",


@@ 1166,6 1218,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"

[[package]]
name = "migrant_lib"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdd763657dd793f0cfb3f5e5e1eb754bf56c38b5bc964696ebc4573cdfd0c240"
dependencies = [
 "chrono",
 "error-chain",
 "lazy_static",
 "log",
 "percent-encoding",
 "postgres",
 "regex",
 "serde",
 "serde_derive",
 "serde_json",
 "toml",
 "url",
 "walkdir",
]

[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1182,12 1255,22 @@ dependencies = [
]

[[package]]
name = "miniz_oxide"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
dependencies = [
 "adler",
 "autocfg",
]

[[package]]
name = "mio"
version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "fuchsia-zircon",
 "fuchsia-zircon-sys",
 "iovec",


@@ 1269,7 1352,7 @@ version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "libc",
 "winapi 0.3.9",
]


@@ 1321,6 1404,12 @@ dependencies = [
]

[[package]]
name = "object"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"

[[package]]
name = "once_cell"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1345,7 1434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4"
dependencies = [
 "bitflags",
 "cfg-if",
 "cfg-if 0.1.10",
 "foreign-types",
 "lazy_static",
 "libc",


@@ 1388,7 1477,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "cloudabi",
 "instant",
 "libc",


@@ 1489,6 1578,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"

[[package]]
name = "postgres"
version = "0.17.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14d864cf6c2eabf1323afe4145ff273aad1898e4f2a3bcb30347715df8624a07"
dependencies = [
 "bytes",
 "fallible-iterator",
 "futures",
 "log",
 "tokio",
 "tokio-postgres",
]

[[package]]
name = "postgres-protocol"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1734,6 1837,12 @@ dependencies = [
]

[[package]]
name = "rustc-demangle"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"

[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1749,6 1858,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"

[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
 "winapi-util",
]

[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1879,7 1997,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1"
dependencies = [
 "block-buffer 0.9.0",
 "cfg-if",
 "cfg-if 0.1.10",
 "cpuid-bool",
 "digest 0.9.0",
 "opaque-debug 0.3.0",


@@ 1919,7 2037,7 @@ version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "libc",
 "redox_syscall",
 "winapi 0.3.9",


@@ 1995,7 2113,7 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "libc",
 "rand",
 "redox_syscall",


@@ 2157,6 2275,15 @@ dependencies = [
]

[[package]]
name = "toml"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
dependencies = [
 "serde",
]

[[package]]
name = "tower-service"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2321,6 2448,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"

[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
dependencies = [
 "same-file",
 "winapi 0.3.9",
 "winapi-util",
]

[[package]]
name = "want"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2342,7 2480,7 @@ version = "0.2.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "serde",
 "serde_json",
 "wasm-bindgen-macro",


@@ 2369,7 2507,7 @@ version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95f8d235a77f880bcef268d379810ea6c0af2eacfa90b1ad5af731776e0c4699"
dependencies = [
 "cfg-if",
 "cfg-if 0.1.10",
 "js-sys",
 "wasm-bindgen",
 "web-sys",


@@ 2443,6 2581,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
 "winapi 0.3.9",
]

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

M Cargo.toml => Cargo.toml +1 -0
@@ 51,6 51,7 @@ ammonia = "3.1.0"
base64 = "0.13.0"
pdcm-linkify = { git = "https://git.sr.ht/~vpzom/pdcm-linkify", rev = "18c43df5" }
pulldown-cmark = "0.8.0"
migrant_lib = { version = "0.30.0", features = ["d-postgres"] }

[dev-dependencies]
rand = "0.7.3"

A build.rs => build.rs +34 -0
@@ 0,0 1,34 @@
use std::io::Write;

const MIGRATIONS_DIR: &str = "migrations";

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("cargo:rerun-if-changed={}", MIGRATIONS_DIR);

    let out_dir = std::env::var("OUT_DIR")?;
    let mut out_file = std::fs::File::create(std::path::Path::new(&out_dir).join("migrations.rs"))?;
    writeln!(out_file, "&[")?;

    let paths: Result<Vec<_>, _> = std::fs::read_dir(MIGRATIONS_DIR)?.collect();
    let mut paths = paths?;

    paths.sort_by_cached_key(|entry| entry.file_name());

    for entry in paths {
        let filename = entry.file_name();
        let tag = filename.to_str().unwrap();

        let path = entry.path().canonicalize()?;
        let path = path.to_str().unwrap();

        writeln!(
            out_file,
            r##"StaticMigration {{ tag: r#"{}"#, up: include_str!(r#"{1}/up.sql"#), down: include_str!(r#"{1}/down.sql"#) }},"##,
            tag, path
        )?;
    }

    write!(out_file, "]")?;

    Ok(())
}

M src/main.rs => src/main.rs +14 -1
@@ 8,6 8,7 @@ use std::sync::Arc;
use trout::hyper::RoutingFailureExtHyper;

mod apub_util;
mod migrate;
mod routes;
mod tasks;
mod worker;


@@ 906,8 907,20 @@ pub fn on_post_add_comment(comment: CommentInfo<'static>, ctx: Arc<crate::RouteC
    });
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut args = std::env::args();
    args.next(); // discard first element
    match args.next().as_deref() {
        Some("migrate") => Ok(crate::migrate::run(args)),
        None => run(),
        _ => {
            panic!("Unexpected argument");
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn run() -> Result<(), Box<dyn std::error::Error>> {
    let host_url_apub =
        std::env::var("HOST_URL_ACTIVITYPUB").expect("Missing HOST_URL_ACTIVITYPUB");


A src/migrate.rs => src/migrate.rs +96 -0
@@ 0,0 1,96 @@
pub const MIGRATIONS: &[StaticMigration] = include!(concat!(env!("OUT_DIR"), "/migrations.rs"));

pub struct StaticMigration {
    tag: &'static str,
    up: &'static str,
    down: &'static str,
}

pub fn run(mut args: std::env::Args) {
    let action = args.next();
    let action = action.as_deref().unwrap_or("up");

    let database_url = std::env::var("DATABASE_URL").expect("Missing DATABASE_URL");
    let db_cfg: tokio_postgres::Config =
        database_url.parse().expect("Failed to parse DATABASE_URL");

    let mut settings = migrant_lib::Settings::configure_postgres();
    settings
        .database_name(db_cfg.get_dbname().expect("Missing dbname"))
        .database_user(db_cfg.get_user().expect("Missing user"))
        .database_password(
            std::str::from_utf8(db_cfg.get_password().expect("Missing password")).unwrap(),
        );

    let hosts = db_cfg.get_hosts();
    if !hosts.is_empty() {
        let host = hosts
            .iter()
            .filter_map(|host| match host {
                tokio_postgres::config::Host::Tcp(hostname) => Some(hostname),
                _ => None,
            })
            .next();

        match host {
            None => panic!("Unsupported host type"),
            Some(hostname) => {
                settings.database_host(hostname);
            }
        }
    }

    let ports = db_cfg.get_ports();
    if !ports.is_empty() {
        if ports.len() == 1 {
            settings.database_port(ports[0]);
        } else {
            panic!("Multiple ports are not supported");
        }
    }

    let settings = settings.build().unwrap();

    let mut config = migrant_lib::Config::with_settings(&settings);
    config.use_cli_compatible_tags(true);

    if action == "setup" {
        config.setup().expect("Failed to setup database");
    } else {
        let migrations: Vec<_> = MIGRATIONS
            .iter()
            .map(|item| {
                migrant_lib::EmbeddedMigration::with_tag(item.tag)
                    .up(item.up)
                    .down(item.down)
                    .boxed()
            })
            .collect();
        config
            .use_migrations(&migrations)
            .expect("Failed to initialize migrations");

        let config = config.reload().expect("Failed to check status");

        match action {
            "up" => {
                println!("Applying migrations...");
                migrant_lib::Migrator::with_config(&config)
                    .all(true)
                    .swallow_completion(true)
                    .apply()
                    .expect("Failed to apply migrations");
            }
            "down" => {
                println!("Unapplying migration...");
                migrant_lib::Migrator::with_config(&config)
                    .direction(migrant_lib::Direction::Down)
                    .all(false)
                    .swallow_completion(true)
                    .apply()
                    .expect("Failed to undo migration");
            }
            _ => panic!("Unknown migrate action"),
        }
    }
}