Quel idiot a écrit ce code ?
Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →
C'est finalement arrivé, j'ai introduit un bug qui n'apparaît que dans un seul cas d'usage et qui reste insoluble car résultant de l'utilisation simultanée d'une ancienne et d'une nouvelle version d'Oh My Posh. Qui fait ça, demanderez-vous ? Cela peut survenir si vous utilisez WSL sous Windows, ou des VM sur n'importe quel système tout en partageant la même configuration entre installations. Ce n'est pas le cas principal, mais pas non plus exotique.
Que s'est-il passé ?
Début d'année, après une lutte assez intense, j'ai enfin pu livrer la mise à jour architecturale la plus importante depuis la réécriture en Go. Cela a nécessité une migration des anciennes configurations pour éviter aux utilisateurs l'épreuve de déterminer les correspondances - processus très logique où les ordinateurs excellent évidemment.
Pour faciliter cela, j'ai ajouté une propriété version dans la configuration, qu'on peut incrémenter quand celle-ci évolue, déclenchant une migration automatique si nécessaire. La logique pour identifier le besoin de migration est la suivante :
if !env.Flags().Migrate && cfg.Version != configVersion {
cfg.BackupAndMigrate(env)
}
Si vous êtes observateur, vous avez peut-être déjà repéré le problème maintenant que vous connaissez le cas d'usage. Pour ceux qui préfèrent lire plutôt que réfléchir, le résultat est assez simple : la migration s'exécutera toujours, soit manuellement via oh-my-posh config migrate, soit quand la version config actuelle ne correspond pas à la version requise. Simple, non ? Cela fonctionne comme prévu lors des mises à jour normales. Le problème survient avec une configuration partagée et des versions multiples d'Oh My Posh sur la même machine.
Imaginez travailler avec plusieurs shells : un WSL Ubuntu utilisant Oh My Posh version 1 (S1). Un jour, vous mettez à jour PowerShell sous Windows vers la dernière version, utilisant la v2 (S2). Au lancement de S2, la config migre automatiquement en version 2, déplaçant la propriété template dans le modèle de segment.
Concrètement, cette configuration version 1 :
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"version": 1,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"background": "#9A348E",
"foreground": "#ffffff",
"leading_diamond": "\ue0b6",
"properties": {
"template": "{{ .UserName }} "
},
"style": "diamond",
"type": "session"
}
]
}
]
}
Est migrée en :
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"version": 2,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"background": "#9A348E",
"foreground": "#ffffff",
"leading_diamond": "\ue0b6",
"template": "{{ .UserName }} ",
"style": "diamond",
"type": "session"
}
]
}
]
}
Parfait, aucune interaction utilisateur et tout fonctionne comme prévu. Cependant, si vous utilisez maintenant S1, Oh My Posh détecte que 2 != 1 et déclenche la migration pour la version 1. Bien que non destructrice, cette migration pose problème car Oh My Posh ne reconnaît pas la propriété template sur segment dans ce contexte. Le résultat final de notre configuration devient particulièrement gênant, nous laissant avec ceci :
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"version": 1,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"background": "#9A348E",
"foreground": "#ffffff",
"leading_diamond": "\ue0b6",
"style": "diamond",
"type": "session"
}
]
}
]
}
😱 le template a disparu ! Pas de panique : Oh My Posh utilisera le template par défaut pour afficher votre invite. La migration a aussi créé une sauvegarde de votre config v2 correcte. Vous pouvez encore revenir en arrière - dommage, mais vos ajustements locaux restent disponibles. Si vous continuez à utiliser S2 à ce stade, il relancera la migration vers la v2 et écrasera votre sauvegarde avec la config v1 défectueuse.
Bien que le correctif code soit trivial, il est impossible de le déployer sur les anciennes versions. Les utilisateurs mettront à jour vers la version récente, ce qui peut causer des ruptures dans ce scénario spécifique. La solution est de mettre à jour toutes les versions simultanément, pour ne migrer qu'une fois sans laisser d'ancienne version déclencher cet effet secondaire indésirable.
Le correctif est disponible dans 7.52.1, mais pour des raisons évidentes, il ne fonctionnera qu'à partir de la version 2 vers les futures versions de configuration.
if !env.Flags().Migrate && cfg.Version < configVersion {
cfg.BackupAndMigrate(env)
}
Bien que je m'efforce d'anticiper tous les cas limites possibles lors de la validation de cette logique, certaines choses échappent parfois à l'attention. Même en examinant ce cas précis, je trouve difficile de justifier pourquoi je n'ai pas envisagé ce scénario, mais c'est pourtant arrivé. La bonne nouvelle ? Cela ne se reproduira plus 😅