Skip to main content

track_core/
migration.rs

1use serde::{Deserialize, Serialize};
2
3pub const MIGRATION_STATUS_SETTING_KEY: &str = "migration_status";
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "snake_case")]
7pub enum MigrationState {
8    Ready,
9    ImportRequired,
10    Imported,
11    // The skip flow was removed, but we still accept the legacy serialized
12    // value so older backend_settings rows do not become unreadable.
13    Skipped,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
17pub struct LegacyScanSummary {
18    #[serde(rename = "projectsFound")]
19    pub projects_found: usize,
20    #[serde(rename = "aliasesFound")]
21    pub aliases_found: usize,
22    #[serde(rename = "tasksFound")]
23    pub tasks_found: usize,
24    #[serde(rename = "taskDispatchesFound")]
25    pub task_dispatches_found: usize,
26    #[serde(rename = "reviewsFound")]
27    pub reviews_found: usize,
28    #[serde(rename = "reviewRunsFound")]
29    pub review_runs_found: usize,
30    #[serde(rename = "remoteAgentConfigured")]
31    pub remote_agent_configured: bool,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35pub struct SkippedLegacyRecord {
36    pub kind: String,
37    pub path: String,
38    pub error: String,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
42pub struct CleanupCandidate {
43    pub path: String,
44    pub reason: String,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
48pub struct MigrationStatus {
49    pub state: MigrationState,
50    #[serde(rename = "requiresMigration")]
51    pub requires_migration: bool,
52    #[serde(rename = "canImport")]
53    pub can_import: bool,
54    #[serde(rename = "legacyDetected")]
55    pub legacy_detected: bool,
56    pub summary: LegacyScanSummary,
57    #[serde(rename = "skippedRecords", default)]
58    pub skipped_records: Vec<SkippedLegacyRecord>,
59    #[serde(rename = "cleanupCandidates", default)]
60    pub cleanup_candidates: Vec<CleanupCandidate>,
61}
62
63impl MigrationStatus {
64    pub fn ready() -> Self {
65        Self {
66            state: MigrationState::Ready,
67            requires_migration: false,
68            can_import: false,
69            legacy_detected: false,
70            summary: LegacyScanSummary::default(),
71            skipped_records: Vec::new(),
72            cleanup_candidates: Vec::new(),
73        }
74    }
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
78pub struct MigrationImportSummary {
79    #[serde(rename = "importedProjects")]
80    pub imported_projects: usize,
81    #[serde(rename = "importedAliases")]
82    pub imported_aliases: usize,
83    #[serde(rename = "importedTasks")]
84    pub imported_tasks: usize,
85    #[serde(rename = "importedTaskDispatches")]
86    pub imported_task_dispatches: usize,
87    #[serde(rename = "importedReviews")]
88    pub imported_reviews: usize,
89    #[serde(rename = "importedReviewRuns")]
90    pub imported_review_runs: usize,
91    #[serde(rename = "remoteAgentConfigImported")]
92    pub remote_agent_config_imported: bool,
93    #[serde(rename = "copiedSecretFiles", default)]
94    pub copied_secret_files: Vec<String>,
95    #[serde(rename = "skippedRecords", default)]
96    pub skipped_records: Vec<SkippedLegacyRecord>,
97    #[serde(rename = "cleanupCandidates", default)]
98    pub cleanup_candidates: Vec<CleanupCandidate>,
99}