Unisci due siti Discourse in uno

Se hai due siti Discourse che vorresti fossero uno, questa guida è per te.

Esiste uno strumento chiamato discourse_merger che può prendere un sito Discourse e fonderlo in un altro.

Prerequisiti

Questo non è un compito facile e dovrebbe essere trattato come qualsiasi altra migrazione a Discourse. Non eseguirai discourse_merger su un sito di produzione attivo. Eseguirai la fusione in un altro ambiente dove puoi esaminare l’output prima di spostare il risultato in produzione.

Copia vs Fusione

Quasi tutto verrà copiato da un sito all’altro, ma Categorie e Utenti possono essere fusi, il che eviterà duplicazioni.

  • Gli Utenti verranno fusi se un utente su entrambi i siti ha lo stesso indirizzo email.
  • Le Categorie verranno fuse se hanno lo stesso nome.

Se desideri riorganizzare i tuoi dati, fallo prima della fusione.

Scegli il sito di destinazione

Scegli quale sito sarà la destinazione per i dati. Questo è quello che conserverà tutto il suo stile e le sue impostazioni. L’altro sito avrà i suoi utenti, categorie, argomenti, post, caricamenti, ecc. copiati/fusi nel sito di destinazione.

Come fare

Esegui backup di entrambi i siti inclusi i file e copiali nell’ambiente in cui eseguirai la fusione. È possibile che provengano da versioni diverse di Discourse, quindi dobbiamo far sì che siano alla stessa versione. Io sceglierei di utilizzare la versione più recente di Discourse durante l’esecuzione della fusione.

Ripristina il sito di destinazione nell’ambiente di fusione. Se lo fai dalla riga di comando:

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

Successivamente estrarremo l’altro sito.

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

L’output includerà il dump del database e i file di caricamento.

Crea un database con i dati:

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

Se stai eseguendo l’importazione in un container Docker ufficiale (consigliato), dovrai reimpostare la password di postgres per fornirla allo script, altrimenti potresti riscontrare un errore in cui l’utente postgres non può accedere al database.

Per cambiare la password:

sudo -u postgres psql
\password postgres
(inserisci la nuova password)
\q

Ora è il momento di eseguire lo script. Alcune variabili d’ambiente che imposterai:

DB_NAME: nome del database che viene fuso nel sito di destinazione.
DB_HOST: (opzionale) nome host del database che viene fuso. Lascia vuoto se è locale.
DB_PASS: password per l’utente postgres per accedere al database
UPLOADS_PATH: percorso assoluto (sito che viene fuso) della directory contenente le directory “original” e “optimized”. Es. /path/to/data/uploads/default
SOURCE_BASE_URL: url di base del sito che viene fuso. Es. https://meta.discourse.org
SOURCE_CDN: (opzionale) url di base del CDN del sito che viene fuso.

Potrebbe essere necessario eseguire un bundle install prima di eseguire lo script di importazione per evitare errori. Per farlo:

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

Al primo avvio, potrebbe essere necessario installare alcune dipendenze aggiuntive per le gem richieste nell’importazione.

Una volta completato il bundle, esegui l’importazione.

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'

Quando ha finito, esamina l’output in un browser web.

Puoi usare lo strumento remap per aggiornare i link dal vecchio forum.

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

Inoltre riesegui il baking di tutti i post con caricamenti:

rake posts:rebake_match["upload:"]

Se tutto sembra a posto, esegui un backup del risultato e ripristinalo sul tuo server di produzione.

bundle exec ruby script/discourse backup
45 Mi Piace

Sembra funzionare, ma quando eseguo un backup ottengo

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

È molto strano.

EDIT: risolto con

ALTER USER discourse WITH SUPERUSER;
1 Mi Piace

Qualcuno l’ha usato di recente? Com’è andata?

Inoltre, qualcuno sa se è possibile inserire automaticamente gli utenti in un gruppo per ogni forum di origine? (Per rendere più facile concedere loro i permessi per visualizzare gli argomenti dei forum da cui provengono.)

È stato un po’ complicato. Penso di aver dovuto commentare alcune cose. C’è stato anche un problema con le immagini di unione.

Penso che aggiungerei tutti gli utenti del nuovo sito a qualche gruppo in modo che siano in quel gruppo quando li unirai. Sarebbe più facile che farlo dopo o come parte dell’unione.

2 Mi Piace

L’ultima volta che l’ho fatto, i caricamenti dal sito unito erano tutti mancanti. Ho ottenuto un elenco dei caricamenti da tar tf backupfile.tar.gz e li ho inseriti in allfiles.txtx e l’ho copiato nella directory uploads. Questo script (che probabilmente non funzionerà per te senza modifiche) ha creato un caricamento per ciascuno di quei file, quindi rifacendo i post ha corretto tutte (o la maggior parte?) le immagini mancanti.

def process_uploads
  begin
    # Leggi l'elenco dei nomi dei file
    filenames = File.readlines('/shared/uploads/allfiles.txt').map(&:strip)
    count = 0

    filenames.each do |filename|
      # Prependi /shared al nome del file
      filename.gsub!(/\.\//,"")
      full_path = File.join('/shared/uploads/default/original/', filename)

      begin
        # Verifica se il percorso esiste ed è un file regolare (non una directory)
        count += 1
        
        if File.exist?(full_path) && File.file?(full_path)
          # Apri il file
          File.open(full_path, 'r') do |tempfile|
            # Crea il caricamento utilizzando i parametri specificati
            u = UploadCreator.new(tempfile, 'imported', {}).create_for(-1)
            puts "#{count} -- #{u.id}: #{u.url}"
          end
        else
          puts "Attenzione: Percorso non trovato o non è un file regolare: #{full_path}"
        end
      rescue => e
        puts "Errore nell'elaborazione del file #{full_path}: #{e.message}"
        # Continua con il file successivo anche se quello corrente fallisce
        next
      end
    end
  rescue Errno::ENOENT
    puts "Errore: Impossibile trovare files.txt"
  rescue => e
    puts "Errore nella lettura di files.txt: #{e.message}"
  end
end

# Esegui l'elaborazione
process_uploads;

Ho ottenuto i post errati in questo modo:

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

e poi questo per marcarli come bisognosi di un rebake:

bad.update_all(baked_version: nil)

Ero impaziente, quindi ho usato

rake posts:rebake_uncooked_posts

per rifarli.

2 Mi Piace

Mi chiedo se non sarebbe più facile convertire il forum discourse che voglio unire in xenforo (i loro importatori sono solitamente eccellenti) quindi unirlo con gli altri forum che voglio far parte dell’unione (che a loro volta verranno convertiti in xenforo da vbulletin) e poi infine importare il nuovo forum xenforo unito in discourse..