Data Schema Migration
Runeya maintains backwards compatibility with previous versions of ./.runeya/ via an automatic migration system at startup.
How It Works
Au démarrage, le serveur lit schema-version.json et applique les migrations nécessaires dans l'ordre :
schema-version.json: { "version": 2 }
│
migrations disponibles
v2 → v3 (appliquée)
│
schema-version.json: { "version": 3 }Available Migrations
migrate-from-legacy.ts (v1 → v3)
Migration principale depuis le format legacy :
- Crée des environnements service-scoped depuis les anciens
inheritAllEnvetserviceVariables - Supprime les champs obsolètes
- Met à jour le schéma de version
Adding a Migration
typescript
// apps/server/src/migrations/v3-to-v4.ts
export async function migrateV3ToV4(dataDir: string): Promise<void> {
const services = await readJson(join(dataDir, 'services.json'))
const migrated = services.map(service => ({
...service,
newField: 'default-value', // nouveau champ avec valeur par défaut
}))
await writeJsonAtomic(join(dataDir, 'services.json'), migrated)
}Puis dans le runner de migrations :
typescript
// apps/server/src/migrations/index.ts
const migrations = [
{ from: 1, to: 3, fn: migrateFromLegacy },
{ from: 3, to: 4, fn: migrateV3ToV4 }, // nouvelle
]Atomic Writes
Toutes les migrations utilisent l'écriture atomique pour éviter la corruption :
typescript
async function writeJsonAtomic(path: string, data: unknown): Promise<void> {
const tmp = path + '.tmp'
await fs.writeFile(tmp, JSON.stringify(data, null, 2))
await fs.rename(tmp, path) // atomique sur POSIX
}Backup Before Migration
TIP
Runeya automatically creates a backup of ./.runeya/ before applying migrations. Backups are stored in ./.runeya/backups/.