Potion Bottle Icon Manuel d'alchimie du code Potion Bottle Icon

Migrer de Slack à Mattermost : récit d'une migration préservée

- 828 mots - Temps de lecture estimé: 5 minutes

TL;DR : J’ai été mandaté par la communauté de recherche Accès aux données (aujourd’hui DALIAS). Pour faire la migration des données, une fois le serveur Mattermost configuré, j’ai développé un notebook Python pour migrer les utilisateurs, messages et canaux d’un fichier d’exportation de Slack vers Mattermost via l’API REST.

Consulte d’abord l’étude de cas complète pour comprendre le contexte et les défis de cette migration.

🌘 La mission

En 2023, la communauté de recherche Accès aux données, devenue depuis DALIAS, utilisait Slack depuis plusieurs années. Les forfaits de Slack étaient passé du nombre de message à une expiration des contenus après 90 jours. Étant une communauté nombreuse, mais avec une fréquence de publication réduite, on cherchait une alternative pour répondre aux besoins de préservation des données et de maîtrise des coûts.

Comme on faisait une migration, il fallait préserver trois types de données :

  1. Les utilisateurs — leurs comptes et leur niveau d’accès (régulier ou administrateur)
  2. Les canaux — leur structure, leurs descriptions, leur organisation
  3. Les messages — l’historique des conversations

J’ai été mandaté pour exécuter cette migration. Je te partage comment j’ai fait ça.

🌘 L’exportation de Slack : point de départ

Tout commence par un export Slack. Le workspace est archivé côté Slack, et on récupère une archive ZIP contenant des fichiers JSON. Les deux fichiers importants pour faire la migration sont:

🌘 La solution technique

J’ai choisi un notebook Jupyter comme outil parce que c’est itératif et surtout, un one-shot. On peut inspecter chaque étape, rattraper une erreur, et documenter le travail à mesure. L’idée ici n’est pas nécessairement l’automatisation ou la reproductibilité d’un point de vue scientifique, mais surtout de pouvoir expliquer facilement les différents glitch de données qui allaient survenir. Parce que ça marche jamais à 100%, ce genre de migration là !

Le notebook fait trois choses :

  1. S’authentifier à l’API de Mattermost via un bearer token
  2. Migrer les utilisateurs avec une logique de fallback en trois temps
  3. Extraire les canaux non archivés pour référence

🌘 Connexion à Mattermost

import mattermost

mm = mattermost.MMApi(api_url)
mm.login(bearer=bearer_token)

La librairie mattermost de Python permet d’accéder à l’API REST. L’authentification par token est plus fiable qu’un couple login/mot de passe pour de l’automatisation.

🌘 La logique de correspondance des utilisateurs

Pour chaque utilisateur Slack, je tente trois stratégies dans l’ordre. La raison ici, c’est qu’il y a eu création de compte sur la nouvelle plateforme avant la migration de toutes les données, étant donné que c’était un groupe public, il y a plusieurs personnes avec plusieurs comptes, et des adresses inactives au fil du temps. Je ne pouvais pas enregistrer ces comptes là, donc je devais matcher les données avec le nouveau compte.

for user in users:
    slack_email = user["profile"]['email']
    slack_username = user['name']
    slack_name = user['real_name']

    # 1. Recherche par email
    try:
        mattermost_user = mm._get(f"/v4/users/email/{slack_email}")
        mm.add_user_to_team(user_id=mattermost_user['id'], team_id=team_id)
        # ✅ utilisateur trouvé et ajouté
    except:
        # 2. Recherche par nom d'utilisateur
        try:
            mattermost_user = mm._get(f"/v4/users/username/{slack_username}")
            mm.add_user_to_team(user_id=mattermost_user['id'], team_id=team_id)
        except:
            # 3. Création d'un nouveau compte
            password = generer_mot_de_passe()
            mm._post(endpoint="/v4/users", data={
                "email": slack_email,
                "username": slack_username,
                "password": password
            })

Pourquoi cette approche en trois étapes ?

🌘 Découpage des noms

Slack stocke le nom complet dans real_name (ex: « Jean Dupont »). Mattermost attend un first_name et un last_name séparés. Une simple regex fait l’affaire pour la plupart des gens au Canada, et pour les autres, on corrige manuellement :

def split_name(name):
    pattern = re.compile(r'^(.+)\s([^\s]+)$')
    match = pattern.match(name)
    if match:
        return match.group(1), match.group(2)
    return None

🌘 Inventaire des canaux

La deuxième partie du notebook liste les canaux non archivés. Cela permet de documenter la structure existante et de la recréer du côté de Mattermost :

with open(data_path / 'channels.json', 'r') as f:
    data_channels = json.load(f)

noms_canaux = [c['name'] for c in data_channels if not c.get('is_archived')]
display_name_canaux = [c['display_name'] for c in data_channels if not c.get('is_archived')]
purpose_canaux = [c['purpose']['value'] for c in data_channels if not c.get('is_archived')]

🌘 Migration des messages

J’ai évoqué plus haut la préservation des messages. Mattermost propose un outil en ligne de commande, mattermost import, qui accepte le format d’export JSON de Slack. En théorie, c’est simple. En pratique, la taille des exports et le mapping des IDs utilisateurs demandent de la préparation.

🌘 Concl;usion

En quelques minutes, le notebook a migré l’ensemble des utilisateurs de la communauté Accès aux données vers Mattermost. Tous les comptes actifs ont été préservés. Ce qui aurait pris des heures à la main a été automatisé avec un outil rudimentaire mais efficace : un notebook, quelques appels API, et une logique de fallback pour fusionner les comptes.

Pour une vue d’ensemble du projet, lis l’étude de cas complète.

Tu aimerais migrer ta communauté vers des logiciels libres ? C’est ce que j’offre avec La grande évasion !

Abonne-toi au fil RSS pour ne rien manquer.

Étiquettes