Run migrations on development server start (#3971)

Conrad Irwin created

Release Notes:

- N/A

Change summary

crates/collab/src/lib.rs  |  6 ++++++
crates/collab/src/main.rs | 19 +++++++++++++++++++
2 files changed, 25 insertions(+)

Detailed changes

crates/collab/src/lib.rs 🔗

@@ -103,6 +103,12 @@ pub struct Config {
     pub zed_environment: Arc<str>,
 }
 
+impl Config {
+    pub fn is_development(&self) -> bool {
+        self.zed_environment == "development".into()
+    }
+}
+
 #[derive(Default, Deserialize)]
 pub struct MigrateConfig {
     pub database_url: String,

crates/collab/src/main.rs 🔗

@@ -53,6 +53,25 @@ async fn main() -> Result<()> {
             let config = envy::from_env::<Config>().expect("error loading config");
             init_tracing(&config);
 
+            if config.is_development() {
+                // sanity check database url so even if we deploy a busted ZED_ENVIRONMENT to production
+                // we do not run
+                if config.database_url != "postgres://postgres@localhost/zed" {
+                    panic!("about to run development migrations on a non-development database?")
+                }
+                let migrations_path = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/migrations"));
+                let db_options = db::ConnectOptions::new(config.database_url.clone());
+                let db = Database::new(db_options, Executor::Production).await?;
+
+                let migrations = db.migrate(&migrations_path, false).await?;
+                for (migration, duration) in migrations {
+                    println!(
+                        "Ran {} {} {:?}",
+                        migration.version, migration.description, duration
+                    );
+                }
+            }
+
             let state = AppState::new(config).await?;
 
             let listener = TcpListener::bind(&format!("0.0.0.0:{}", state.config.http_port))