forge_runtime/migrations/
builtin.rs1use super::runner::Migration;
17
18pub const SYSTEM_MIGRATION_PREFIX: &str = "__forge_v";
20
21pub const LEGACY_MIGRATION_NAME: &str = "0000_forge_internal";
24
25const V001_INITIAL: &str = include_str!("../../migrations/system/v001_initial.sql");
28
29#[derive(Debug, Clone)]
31pub struct SystemMigration {
32 pub version: u32,
34 pub sql: &'static str,
36 pub description: &'static str,
38}
39
40impl SystemMigration {
41 pub fn name(&self) -> String {
43 format!("{}{:03}", SYSTEM_MIGRATION_PREFIX, self.version)
44 }
45
46 pub fn to_migration(&self) -> Migration {
48 Migration::new(self.name(), self.sql)
49 }
50}
51
52pub fn get_system_migrations() -> Vec<SystemMigration> {
56 vec![SystemMigration {
57 version: 1,
58 sql: V001_INITIAL,
59 description: "Initial FORGE schema with jobs, workflows, crons, and observability",
60 }]
61}
62
63pub fn get_builtin_migrations() -> Vec<Migration> {
65 get_system_migrations()
66 .into_iter()
67 .map(|m| m.to_migration())
68 .collect()
69}
70
71pub fn get_all_system_sql() -> String {
76 get_system_migrations()
77 .into_iter()
78 .map(|m| m.sql)
79 .collect::<Vec<_>>()
80 .join("\n\n")
81}
82
83pub fn is_system_migration(name: &str) -> bool {
85 name.starts_with(SYSTEM_MIGRATION_PREFIX) || name == LEGACY_MIGRATION_NAME
86}
87
88pub fn extract_version(name: &str) -> Option<u32> {
91 if name == LEGACY_MIGRATION_NAME {
92 return Some(1);
93 }
94 if let Some(suffix) = name.strip_prefix(SYSTEM_MIGRATION_PREFIX) {
95 return suffix.parse().ok();
96 }
97 None
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_get_system_migrations() {
106 let migrations = get_system_migrations();
107 assert!(!migrations.is_empty());
108 assert_eq!(migrations[0].version, 1);
109 assert_eq!(migrations[0].name(), "__forge_v001");
110 }
111
112 #[test]
113 fn test_migration_sql_not_empty() {
114 let migrations = get_system_migrations();
115 for m in migrations {
116 assert!(!m.sql.is_empty(), "Migration v{} has empty SQL", m.version);
117 }
118 }
119
120 #[test]
121 fn test_migration_sql_contains_tables() {
122 let migrations = get_system_migrations();
123 let sql = migrations[0].sql;
124
125 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_nodes"));
127 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_leaders"));
128 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_jobs"));
129 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_cron_runs"));
130 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_workflow_runs"));
131 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_workflow_steps"));
132 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_metrics"));
133 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_logs"));
134 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_traces"));
135 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_sessions"));
136 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_subscriptions"));
137 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_alert_rules"));
138 assert!(sql.contains("CREATE TABLE IF NOT EXISTS forge_alerts"));
139 }
140
141 #[test]
142 fn test_is_system_migration() {
143 assert!(is_system_migration("__forge_v001"));
144 assert!(is_system_migration("__forge_v002"));
145 assert!(is_system_migration("__forge_v100"));
146 assert!(is_system_migration("0000_forge_internal")); assert!(!is_system_migration("0001_create_users"));
148 assert!(!is_system_migration("user_migration"));
149 }
150
151 #[test]
152 fn test_extract_version() {
153 assert_eq!(extract_version("__forge_v001"), Some(1));
154 assert_eq!(extract_version("__forge_v002"), Some(2));
155 assert_eq!(extract_version("__forge_v100"), Some(100));
156 assert_eq!(extract_version("0000_forge_internal"), Some(1)); assert_eq!(extract_version("0001_create_users"), None);
158 assert_eq!(extract_version("invalid"), None);
159 }
160
161 #[test]
162 fn test_system_migration_to_migration() {
163 let sys = SystemMigration {
164 version: 1,
165 sql: "SELECT 1;",
166 description: "Test",
167 };
168 let m = sys.to_migration();
169 assert_eq!(m.name, "__forge_v001");
170 assert_eq!(m.up_sql, "SELECT 1;");
171 }
172}