migrator: Add versioned migrations (#26215)

There is a drawback to how we currently write our migrations:

For example:

1. Suppose we change one of our actions from a string to an array and
rename it, then roll out the preview build:

      Before: `"ctrl-x": "editor::GoToPrevHunk"`
Latest: `"ctrl-x": ["editor::GoToPreviousHunk", { "center_cursor": true
}]`
      
To handle this, we wrote migration `A` to convert the string to an
array.

2. Now, suppose we decide to change it back to a string:
- User who hasn't migrated yet on Preview: `"ctrl-x":
"editor::GoToPrevHunk"`
- User who has migrated on Preview: `"ctrl-x":
["editor::GoToPreviousHunk", { "center_cursor": true }]`
    - Latest: `"ctrl-x": "editor::GoToPreviousHunk"`

To handle this, we would need to remove migration `A` and add two more
migrations:
- **Migration B**: `"ctrl-x": "editor::GoToPrevHunk"` -> `"ctrl-x":
"editor::GoToPreviousHunk"`
- **Migration C**: `"ctrl-x": ["editor::GoToPreviousHunk", {
"center_cursor": true }]` -> `"ctrl-x": "editor::GoToPreviousHunk"`

Nice. But over time, this keeps increasing, making it impossible to
track outdated versions and handle all cases. Missing a case means users
stuck on `"ctrl-x": "editor::GoToPrevHunk"` will remain there and won't
be automatically migrated to the latest state.

---

To fix this, we introduce versioned migrations. Instead of removing
migration `A`, we simply write a new migration that takes the user to
the latest version—i.e., in this case, migration `C`.

- A user who hasn't migrated before will go through both migrations `A`
and `C` in order.
- A user who has already migrated will only go through `C`, since `A`
wouldn't change anything for them.

With incremental migrations, we only need to write migrations on top of
the latest state (big win!), as know internally they all would be on
latest state. You *must not* modify previous migrations. Always create
new ones instead.

This also serves as base for only prompting user to migrate, when
feature reaches stable. That way, preview and stable keymap and settings
are in sync.

cc: @mgsloan @ConradIrwin @probably-neb 

Release Notes:

- N/A
This commit is contained in:
smit 2025-03-06 23:04:48 +05:30 committed by GitHub
parent 6fd9708eee
commit 219d36f589
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 948 additions and 773 deletions

View file

@ -0,0 +1,27 @@
pub(crate) mod m_2025_01_29 {
mod keymap;
mod settings;
pub(crate) use keymap::KEYMAP_PATTERNS;
pub(crate) use settings::{replace_edit_prediction_provider_setting, SETTINGS_PATTERNS};
}
pub(crate) mod m_2025_01_30 {
mod keymap;
mod settings;
pub(crate) use keymap::KEYMAP_PATTERNS;
pub(crate) use settings::SETTINGS_PATTERNS;
}
pub(crate) mod m_2025_03_03 {
mod keymap;
pub(crate) use keymap::KEYMAP_PATTERNS;
}
pub(crate) mod m_2025_03_06 {
mod keymap;
pub(crate) use keymap::KEYMAP_PATTERNS;
}