Introduction
As of Discourse version 3.2.0.beta3, Discourse themes/components can leverage a migrations feature to evolve and alter their settings seamlessly. This feature ensures that updates to themes do not disrupt existing installations by handling changes to settings in a controlled manner.
When to Use Migrations
Common scenarios where migrations are particularly useful:
- Changing the type of a setting (e.g., from a comma-separated string to a list).
- Renaming a setting.
- Modifying the structure or format of the data stored in a setting.
In these scenarios, if the setting type or name is changed in the settings.yml
file without an accompanying migration, existing installations where the setting has been changed from the default value, they will lose the change they’ve made to the setting and potentially break when the theme is updated.
To ensure smooth transition when updating a theme setting, theme developers should ship a migration that instructs Discourse core how to migrate existing state that conforms to the old version of the settings.yml
to the new version.
Migration Files
Migrations are JavaScript files located in the migrations/settings
directory of the theme, following the naming convention XXXX-migration-name.js
. The XXXX
prefix is a version number, starting from 0001
and incrementing sequentially, which dictates the order of execution.
The name should be a concise description of the migration’s purpose, limited to alphanumeric characters, hyphens, and under 150 characters in length. Migrations are executed in ascending order based on the numerical value of their versions.
We recommend that you start with 0001
for the first migration and 0002
for the second migration etc. Note that if a migration’s version is below 1000, then the version must be padded with leading zeros to make it 4 digits long since migration filename must start with 4 digits. For the same reason, it’s not currently possible to have more than 9999 migrations in a theme, but we may change that in the future.
Migration Function
Standard JavaScript features such as classes, functions, arrays, maps etc. are all available for migrations to use. The only expectation from Discourse core is that each migration file must export a default function that serves as the entry point. This function receives a Map
object representing modified theme settings and returns a Map
object reflecting the desired final state of all settings.
Examples
Rename a theme setting:
// filename: 0001-rename-old-setting.js
export default function migrate(settings) {
if (settings.has("old_setting_name")) {
settings.set("new_setting_name", settings.get("old_setting_name"));
settings.delete("old_setting_name");
}
return settings;
}
This migration should be accompanied with the setting rename in the settings.yml
file.
Convert a comma-separated string setting to a proper list:
// filename: 0001-convert-string-setting-to-list.js
export default function migrate(settings) {
if (settings.has("list_setting")) {
const list = settings.get("list_setting").split(",");
settings.set("list_setting", list.join("|"));
}
return settings;
}
Similar to the previous example, this migration should be accompanied with changing the setting type from string
to list
in the settings.yml
file.
Rename a choice of an enum setting:
// filename: 0001-rename-enum-choice.js
export default function migrate(settings) {
if (settings.get("enum_setting") === "old_option") {
settings.set("enum_setting", "new_option");
}
return settings;
}
Add a new item to a list setting:
// filename: 0001-add-item-to-list.js
export default function migrate(settings) {
if (settings.has("list_setting")) {
const list = settings.get("list_setting").split("|");
list.push("new_item");
settings.set("list_setting", list.join("|"));
} else {
settings.set("list_setting", "new_item");
}
return settings;
}
Execution and Error Handling
Migrations run automatically during theme installation and updates. They execute only once; if a migration is altered after successful execution, it will not run again. If a migration fails, the update process stops, and an error message of what went wrong is provided.
If a migration has a bug that results in corrupt state for a setting, then the correct way to fix the problem is to create a new migration that corrects the corrupt state instead of modifying the original migration.
This document is version controlled - suggest changes on github.
Last edited by @JammyDodger 2024-05-26T12:26:08Z
Check document
Perform check on document: