web-dev-qa-db-de.com

Rails 3 und Heroku: beim Push automatisch "rake db: migrate"?

Ich habe ein wenig Ärger mit meinem Heroku Push/Deploy-Prozess, der ansonsten eine Freude zu entdecken und zu verwenden war. 

Wenn ich meiner App eine neue Migration hinzufüge, kann ich sie nur auf den Heroku-Server bringen, indem Sie einen Push an die Heroku-Fernbedienung durchführen. Dies lädt es hoch und startet die App neu. Die Migration wird jedoch nicht ausgeführt, daher muss ich heroku rake db:migrate --app myapp und dann heroku restart --app myapp ausführen. In der Zwischenzeit ist die App defekt, weil die Migrationen nicht ausgeführt wurden und der Code sich auf Felder/Tabellen usw. in der Migration bezieht.

Es muss eine Möglichkeit geben, den Bereitstellungsprozess so zu ändern, dass der rake db:migrate automatisch als Teil des Bereitstellungsprozesses ausgeführt wird. Ich kann das jedoch nicht lösen. 

Ist es etwas, das ich in ein Heroku-Cpanel setze? Ist es eine Option, die ich von der Kommandozeile aus an Heroku übergeben? Ist es ein Git-Haken? Kann mich jemand direkt einstellen? danke, max

61
Max Williams

Hier ist eine Rake-Aufgabe, die alles zu einem Einzeiler zusammenfasst (und auch Rollback unterstützt):

https://Gist.github.com/362873

Sie werden möglicherweise immer noch auf der Demo Ihres Chefs installiert, aber Sie verschwenden keine Zeit damit, zwischen dem git Push und dem rake db:migrate zu tippen.

29

Was ist mit dieser einfachen Befehlskettungslösung:

git Push heroku master && heroku run rake db:migrate

Die Migration wird automatisch ausgeführt, sobald der erste erfolgreich abgeschlossen wurde. Es ist normalerweise 1-2 Sekunden oder weniger.

32
Cristian

Heroku hat jetzt die Möglichkeit, dies als Teil der "Release-Phase" zu behandeln.

Sie können Ihrer release einen Prozess mit dem Namen Procfile hinzufügen, der bei jeder Bereitstellung ausgeführt wird.

Schienen> = 5 Beispiel

release: bundle exec Rails db:migrate

Schienen <5 Beispiel

release: bundle exec rake db:migrate

32
Max Woolf

Ich habe ein benutzerdefiniertes Buildpack erstellt, das Heroku veranlasst, rake db:migrate für Sie automatisch bei der Bereitstellung auszuführen. Es ist nur ein Teil von Herokus Standard-Ruby-Buildpack, jedoch mit der rake db:migrate-Task hinzugefügt.

Um es mit Ihrer App zu verwenden, würden Sie Folgendes tun:

heroku config:set BUILDPACK_URL=https://github.com/dtao/rake-db-migrate-buildpack

Beachten Sie auch, dass Sie die Funktion user-env-compile Heroku Labs aktivieren müssen, damit es funktioniert. So tun Sie das:

heroku labs:enable user-env-compile

Und hier ist mein Beweis, dass dies funktioniert:

rake db:migrate on Heroku deployment

14
Dan Tao

Vielleicht könnten Sie versuchen, Ihre Schema-Commits (Migrationen usw.) von Code-Commits (Modelle, Validierungen usw.) zu trennen.

(Im Folgenden wird davon ausgegangen, dass Ihre Migrationsänderungen NICHT destruktiv sind, da Sie darauf hinweisen, dass die meisten Ihrer Anwendungsfälle abgedeckt sind.)

Ihr Bereitstellungsprozess könnte dann Folgendes sein:

  1. Push-Schema-Änderungen an Heroku
  2. wandern
  3. Geben Sie den Anwendungscode an Heroku weiter

Dies ist natürlich weit von der Form her optimal, ist jedoch ein wirksames Mittel, um Ausfallzeiten in der von Ihnen beschriebenen Situation zu vermeiden: Wenn die App den Code für die dynamischen Felder erhält, ist die Datenbank bereits migriert.

(Natürlich besteht die einfachste Lösung darin, einfach zu schieben und zu migrieren, während Ihr Chef zum Mittagessen geht ;-D.)

Andernfalls, selbst wenn Schemaänderungen automatisch ausgeführt wurden, besteht das Risiko, dass eine Anforderung direkt vor dem Ausführen der Migrationen durchlaufen wird.

9
David Sulc

Nur für diese googling Leute wie ich möchte ich hier eine einfache Lösung geben.

Ich verwende Rails 4 und musste der Bereitstellung von Heroku eine einfache Rake-Aufgabe hinzufügen. Da ich in github die Schaltfläche 'deploy to heroku' benutze, gibt es keine Chance, "heroku run ..." direkt nach der Bereitstellung auszuführen.

Was ich getan habe: Ich erweiterte die Standard-Rake-Task 'assets: clean' die automatisch während einer Bereitstellung auf Heroku ausgeführt wird. Die Aufgabe läuft noch normal, aber ich habe meine eigenen Sachen an sein Ende angehängt. Dies geschieht mit der 'verbessern' Methode. Im folgenden Beispiel füge ich ein db: migrate hinzu, da die meisten Leute dies wahrscheinlich wollen:

# in lib/tasks/assets_clean_enhance.rake
Rake::Task['assets:clean'].enhance do
  Rake::Task['db:migrate'].invoke
end

Ich gebe zu, dass dies keine perfekte Lösung ist. Das Heroku Ruby Buildpack unterstützt jedoch keine andere Möglichkeit. Und das Schreiben meines eigenen Buildbacks war für ein so einfaches Ding ein wenig übertrieben.

5
Kari

Ich habe SmartMigrate buildpack geschrieben Dies ist ein einfaches Heroku-Buildpack, das vor ausstehenden Migrationen nach einem Ruby-Build warnt, wenn neue Migrationen entdeckt werden. Dieses Buildpack ist Teil eines Multipacks mit einem vorausgegangenen Ruby-Buildpack.

Im Hinblick auf andere Lösungen bietet dieses Buildpack drei Vorteile gegenüber diesen:

  1. Kein Wartungsmodus erforderlich
  2. Es sind keine veralteten Ruby Buildpack-Gabeln erforderlich, die am Ende einfach die Migration einfügen
  3. Migrationen müssen NICHT ALLEMAL ausgeführt werden. Eine Warnung wird nur angezeigt, wenn seit der letzten Bereitstellung neue Migrationen erkannt wurden
2
hammady

Ich verwende eine Rake-Task, um die App in den Wartungsmodus zu versetzen, Push, Migration und den Wartungsmodus zu verlassen.

2
Aditya Sanghi

Ich denke, der Ansatz von David Sulc ist der einzige, der dafür sorgt, dass Sie vermeiden, dass Anfragen durchkommen, während sich die App in einem fehlerhaften Zustand befindet.

Es ist ein bisschen schmerzhaft, kann aber unter Umständen notwendig sein.

Wie er feststellte, müssen die Db-Migrationen nicht destruktiv sein. 

Es kann jedoch schwierig sein, Ihre Migrationen und Schemaänderungen vor dem restlichen Code voranzutreiben, da der naheliegende Ansatz ("git Push heroku {revnum}") darauf beruht, dass Sie die Migrationen vor dem restlichen Code überprüft haben.

Wenn Sie das nicht getan haben, können Sie dies immer noch mit einem temporären Zweig tun:

  • Erstellen Sie einen Zweig, der auf der Git-Revision basiert, die Sie zuletzt auf Heroku verschoben haben:

    git branch <branchname> <revnum-or-tag>
    
  • Schauen Sie sich diesen Zweig an:

    git checkout <branchname>
    
  • Wenn Ihre db-Migration nur Migrationen enthält und keine Änderungen am Code vorgenommen werden, wählen Sie die Commits aus, die die Datenbankänderungen enthalten:

    git cherry-pick <revnum1> <revnum2>...
    
  • Wenn Sie Änderungen an der Datenbank in Änderungen vorgenommen haben, die auch Codeänderungen enthielten, können Sie 'git cherry-pick -n' verwenden, das nicht automatisch übernommen wird. Verwenden Sie 'git reset HEAD ", um die Dateien, die keine Db-Änderungen sind, aus der Menge der zu löschenden Dinge zu entfernen. Sobald Sie nur die DB-Änderungen vorgenommen haben, übergeben Sie sie in Ihrem temporären Zweig.

    git cherry-pick -n <revnum1> <revnum2>...
    git reset HEAD <everything that's modified except db/>
    git status
    ... check that everything looks ok ...
    git commit
    
  • Schieben Sie diesen temporären Zweig auf Heroku (idealerweise auf eine Staging-App, um zu überprüfen, ob Sie die richtige Einstellung gefunden haben, da das Vermeiden von Ausfallzeiten der springende Punkt ist, wenn Sie durch diese Reifen springen).

    git Push heroku <branchname>:master
    
  • Führen Sie die Migrationen aus

    heroku run rake db:migrate
    
  • An diesem Punkt könnten Sie denken, Sie könnten "master" zu heroku schieben, um die Codeänderungen zu vermitteln. Dies ist jedoch nicht möglich, da es sich nicht um einen Schnellvorlauf handelt. Um fortzufahren, müssen Sie den Rest von 'master' in Ihren temporären Zweig einbinden und ihn dann wieder mit master zusammenführen, um die Commit-Historien der beiden Zweige neu zu kombinieren:

    git checkout <branchname>
    git merge master
    git diff <branchname> master
    ... shouldn't show any differences, but just check to be careful ...
    git checkout master
    git merge <branchname>
    
  • Jetzt können Sie master wie gewohnt auf heroku drücken, wodurch der Rest Ihrer Codeänderungen angezeigt wird.

Im vorletzten Schritt bin ich nicht zu 100% sicher, ob das Zusammenführen des Masters mit {branchname} erforderlich ist. Auf diese Weise sollte sichergestellt werden, dass eine "Fast-Forward" -Mischung durchgeführt wird. Dies macht git glücklich, wenn Sie auf Heroku drücken. Es ist jedoch möglich, dass Sie dasselbe Ergebnis erzielen, indem Sie einfach {branchname} ohne diesen Schritt mit dem Master verbinden.

Wenn Sie nicht 'master' verwenden, setzen Sie den entsprechenden Zweignamen an den entsprechenden Stellen oben ein.

1
sheltond

Ich habe den Edelstein heroku_san seit einiger Zeit als mein Deployment-Tool verwendet. Es ist ein kleines, fokussiertes Werkzeug für die Push + -Migration. Es werden einige andere Rake-Befehle hinzugefügt, die den Zugriff auf andere Funktionen (z. B. Konsole) erleichtern. Abgesehen davon, dass ich mich nicht an Datenbankmigrationen erinnern muss, ist mein Lieblingsfeature die Heroku-Konfigurationsdatei. Ich kann also alle meine Server (Produktion, Bereitstellung, Spielplatz4, Shirley) nennen, was ich will - und sie im Kopf behalten. 

0
slothbear