Fusionner deux sites Discourse en un seul

Si vous avez deux sites Discourse que vous souhaiteriez fusionner en un seul, ce guide est pour vous.

Il existe un outil appelé discourse_merger qui peut prendre un site Discourse et le fusionner dans un autre.

Prérequis

Ce n’est pas une tâche facile et doit être traitée comme toute autre migration vers Discourse. Vous n’exécuterez pas discourse_merger sur un site de production en direct. Vous effectuerez la fusion dans un autre environnement où vous pourrez examiner le résultat avant de déplacer le résultat vers la production.

Copie vs Fusion

Presque tout sera copié d’un site à l’autre, mais les catégories et les utilisateurs peuvent être fusionnés, ce qui évitera la duplication.

  • Les utilisateurs seront fusionnés si un utilisateur sur les deux sites a la même adresse e-mail.
  • Les catégories seront fusionnées si elles ont le même nom.

Si vous souhaitez effectuer une réorganisation de vos données, faites-le avant de fusionner.

Choisissez le site de destination

Choisissez quel site sera la destination des données. C’est celui qui conservera tout son style et ses paramètres. L’autre site aura ses utilisateurs, catégories, sujets, publications, téléchargements, etc., copiés/fusionnés sur le site de destination.

Comment faire

Sauvegardez les deux sites y compris les fichiers et copiez-les dans l’environnement où vous effectuerez la fusion. Il est possible qu’ils proviennent de différentes versions de Discourse, nous devons donc les mettre à la même version. Je choisirais d’utiliser la version la plus récente de Discourse lors de l’exécution de la fusion.

Restaurez le site de destination dans l’environnement de fusion. Si vous le faites depuis la ligne de commande :

bundle exec ruby script/discourse restore destination-2018-08-02-134227-v2018xxx.tar.gz

Ensuite, nous allons extraire l’autre site.

cd /path/to/data
tar xvzf other-2018-08-02-134227-v2018xxx.tar.gz

Le résultat comprendra la sauvegarde de la base de données et les fichiers de téléchargement.

Créez une base de données avec les données :

psql
CREATE DATABASE "copyme" ENCODING = 'utf8';
\q
gunzip < /path/to/data/other-2018-08-02-134227-v2018xxx.tar.gz | psql -d copyme

Si vous effectuez l’importation dans un conteneur Docker officiel (recommandé), vous devrez réinitialiser le mot de passe postgres pour le fournir au script, sinon vous pourriez rencontrer une erreur indiquant que l’utilisateur postgres ne peut pas accéder à la base de données.

Pour changer le mot de passe :

sudo -u postgres psql
\password postgres
(entrez le nouveau mot de passe)
\q

Maintenant, il est temps d’exécuter le script. Quelques variables d’environnement que vous définirez :

DB_NAME : nom de la base de données en cours de fusion avec le site de destination.
DB_HOST : (optionnel) nom d’hôte de la base de données en cours de fusion. Laissez vide si elle est locale.
DB_PASS : mot de passe pour que l’utilisateur postgres accède à la base de données
UPLOADS_PATH : chemin absolu (du site en cours de fusion) du répertoire contenant les répertoires « original » et « optimized ». ex. /path/to/data/uploads/default
SOURCE_BASE_URL : URL de base du site en cours de fusion. ex. https://meta.discourse.org
SOURCE_CDN : (optionnel) URL de base du CDN du site en cours de fusion.

Vous devrez peut-être exécuter un bundle install avant d’exécuter le script d’importation pour éviter les erreurs. Pour ce faire :

su discourse -c 'bundle config set --local with generic_import && bundle install'

Lors de la première exécution, vous pourriez avoir besoin d’installer des dépendances supplémentaires pour les gems requises dans l’importation.

Une fois le bundle terminé, exécutez l’importation.

su discourse -c 'DB_NAME=copyme DB_PASS=password SOURCE_BASE_URL=http://copy.othersite.com UPLOADS_PATH=/shared/import/data/uploads/default bundle exec ruby script/bulk_import/discourse_merger.rb'

Une fois terminé, examinez le résultat dans un navigateur web.

Vous pouvez utiliser l’outil remap pour mettre à jour les liens de l’ancien forum.

bundle exec ruby script/discourse remap 'copy.othersite.com' 'hot.newsite.com'

Re-cuire également toutes les publications avec des téléchargements :

rake posts:rebake_match["upload:"]

Si tout semble correct, effectuez une sauvegarde du résultat et restaurez-la sur votre serveur de production.

bundle exec ruby script/discourse backup
45 « J'aime »

Il semble que cela fonctionne, mais lorsque j’exécute une sauvegarde, j’obtiens

pg_dump: error: query failed: ERROR:  permission denied for table migration_mappings                                                                                   

C’est très étrange.

EDIT : résolu avec

ALTER USER discourse WITH SUPERUSER;
1 « J'aime »

Quelqu’un l’a-t-il utilisé récemment ? Comment ça s’est passé ?

Sait-on également s’il est possible de mettre automatiquement les utilisateurs dans un groupe pour chaque forum d’origine ? (Pour leur faciliter l’attribution des autorisations de visualisation des sujets des forums dont ils proviennent.)

C’était un peu difficile. Je pense que j’ai dû commenter certaines choses. Il y avait aussi un problème avec les images de fusion.

Je pense que j’ajouterais tous les utilisateurs du nouveau site à un groupe afin qu’ils soient dans ce groupe lorsque vous les fusionnerez. Ce serait plus facile que de le faire après ou dans le cadre de la fusion.

2 « J'aime »

La dernière fois que j’ai fait cela, les téléchargements du site fusionné étaient tous manquants. J’ai obtenu une liste des téléchargements à partir de tar tf backupfile.tar.gz et je les ai mis dans allfiles.txtx et l’ai copié dans le répertoire des téléchargements. Ce script (qui ne fonctionnera probablement pas pour vous sans modification) a créé un téléchargement pour chacun de ces fichiers, puis le re-cuisson des publications a corrigé toutes (ou la plupart ?) des images manquantes.

def process_uploads
  begin
    # Lire la liste des noms de fichiers
    filenames = File.readlines('/shared/uploads/allfiles.txt').map(&:strip)
    count = 0

    filenames.each do |filename|
      # Ajouter /shared au début du nom de fichier
      filename.gsub!(/\.\//,"")
      full_path = File.join('/shared/uploads/default/original/', filename)

      begin
        # Vérifier si le chemin existe et est un fichier régulier (pas un répertoire)
        count += 1
        
        if File.exist?(full_path) && File.file?(full_path)
          # Ouvrir le fichier
          File.open(full_path, 'r') do |tempfile|
            # Créer le téléchargement en utilisant les paramètres spécifiés
            u = UploadCreator.new(tempfile, 'imported', {}).create_for(-1)
            puts "#{count} -- #{u.id}: #{u.url}"
          end
        else
          puts "Attention : Chemin introuvable ou n'est pas un fichier régulier : #{full_path}"
        end
      rescue => e
        puts "Erreur lors du traitement du fichier #{full_path} : #{e.message}"
        # Continuer avec le fichier suivant même si le fichier actuel échoue
        next
      end
    end
  rescue Errno::ENOENT
    puts "Erreur : Impossible de trouver files.txt"
  rescue => e
    puts "Erreur lors de la lecture de files.txt : #{e.message}"
  end
end

# Exécuter le traitement
process_uploads;

J’ai obtenu les mauvaises publications comme ceci :

 bad=Post.where("cooked like '%/images/transparent.png%'")

et ensuite ceci pour les marquer comme nécessitant une re-cuisson :

bad.update_all(baked_version: nil)

J’étais impatient, alors j’ai utilisé

rake posts:rebake_uncooked_posts

pour les re-cuire.

2 « J'aime »

Je me demande s’il ne serait pas plus simple de convertir le forum Discourse que je veux fusionner en XenForo (leurs importateurs sont généralement excellents), puis de le fusionner avec les autres forums que je veux inclure dans la fusion (qui seront eux-mêmes convertis en XenForo depuis vBulletin), puis enfin d’importer le nouveau forum XenForo fusionné dans Discourse…