Continuous Deployment - Aktueller Stand fjorum

Hallo zusammen,

unter anderem hier kam der Vorschlag auf, den aktuellen Entwicklungsstand irgendwo zu deployen, damit schnelleres / mehr / besseres Feedback kommt.
In Absprache mit @Landei habe ich auf meinem Server einen TeamCity installiert, sodass diesem Vorhaben nicht mehr viel entgegen steht.
Der TeamCity ist unter folgender URL zu erreichen: [noparse]http://ci.fjorum.org:8111/[/noparse]
Um den Buildstatus zu sehen, muss man sich nicht anmelden, als Gast kann man sich auch ohne Registrierung einloggen.

Vorerst habe ich nur ganz rudimentäre Build-Profile angelegt:
Eines das ausgeführt wird, wenn es einen commit im Master-Branch gab (dann wird nur kompiliert und getestet) und eines das jede Nacht ausgeführt wird. Dabei wird dann auch das Artefakt gebaut.
Des Weiteren schwebt mir vor eine weitere Konfiguration anzulegen, die einen Build anstößt, wenn in einem Release-Zweig, der gemäß noch zu bestimmenden Konventionen benannt werden muss, ein commit stattfindet.

Den Nightly-Build könnte man unter [noparse]http://nightly.fjorum.org/[/noparse] und den aktuellsten Release-Build unter [noparse]http://stable.fjorum.org/[/noparse] oder so hosten.

Für das Deployment fehlt mir aber noch das notwendige Hintergrundwissen bzw. Ideen, wie man das am bestem umsetzt.
Eine hilfreiche Quelle ist diese Seite, zumindest was die Ninja-spezifischen Details angeht.
Es handelt sich also um eine jar, die ausgeführt werden soll.

Gibt es ein maven-Plugin, sodass man die Anwendung mit einem maven goal starten kann? (Wenn es um maven geht, fällt mir als erstes @maki ein, daher hier ein mention :wink: )
Es müsste dabei aber auch geprüft werden, ob bereits eine Instanz der Anwendung läuft und diese dann ggf. beendet werden.

Der TeamCity und die Webanwendung laufen dann in einem Linux-Container, der PostgreSQL-Server läuft direkt auf dem Server.
Die Localhost-Konfiguration passt daher nicht, ich habe aber in der oben verlinkten Ninja-Seite schon gelesen, dass man mit ninja.external.configuration eine weitere Konfigurationsdatei aktivieren kann, in der man dann den db.connection.url-Wert setzen könnte.
Das selbe gilt für den Port, auf dem die Anwendung lauscht. Da bräuchte man je nach Profil (Nightly / Release) natürlich verschiedene. Man kann ihn über ninja.port konfigurieren.

Vor der/den Webanwendung/en sitzt ein Apache 2.2, der für die Domain/s als Reverse-Proxy konfiguriert wird.

So. Das ist jetzt wahrscheinlich so viel Text, dass sich den niemand durchlesen wird. Aber vielleicht kommen ja doch Anregungen :wink:

Sollten wir mal das Stork-Plugin probieren? Klingt recht simpel: Using Stork to deploy a production Ninja Framework app

Das eigentliche Problem, nämlich die Anwendung wirklich zu starten und eine ggf. schon laufende zu beenden, löst Stork aber nicht. Für die Auslieferung einer “Distribution” der Releases wäre das sicherlich ein schickerer Ansatz als ein nacktes uberjar.

Ein möglicher Ansatz für das Deployment wäre es, Cargo zu verwenden. Dann müsste man aber das war-Artefakt verwenden und einen Container (im Idealfall wohl Jetty) vorkonfigurieren.

Fuer den Build, also die Tests?
Failsafe Plugin, da kann man gleich mit dem Server arbeiten wenn man nur pre-integration-test angibt als Phase, sosnt (verify bzw. install) fuehren auch die Tests dagegen aus.

Fuers Deployment ist Maven nicht wirklich gedacht, hat aber ein paar beschraenkte Moeglichkeiten (Cargo Plugin, Tomcat, Jetty, etc. pp.).
Wenn es um das Deployen einer Jar und das starten dieser auf einer anderen Maschine geht wuerde ich das nicht mit Maven machen, zur Not geht das (maven-deploy-plugin, exec Plugin).

Ansonsten per Shell Script oder aehnliches durch die CI Maschienen machen lassen.

[quote=cmrudolph;115784]Die Localhost-Konfiguration passt daher nicht, ich habe aber in der oben verlinkten Ninja-Seite schon gelesen, dass man mit ninja.external.configuration eine weitere Konfigurationsdatei aktivieren kann, in der man dann den db.connection.url-Wert setzen könnte.
Das selbe gilt für den Port, auf dem die Anwendung lauscht. Da bräuchte man je nach Profil (Nightly / Release) natürlich verschiedene. Man kann ihn über ninja.port konfigurieren.[/quote]
MIt dem Resource Filtering von Maven koennte ma so Properties auf Profilen einsetzen.
D.h. Standard Properties sind ohne Profil in der POM und beziehen sich per default immer auf DEV, also zB. eine H2/HSQL/Derby DB anstatt der echten (Postgres).
Ein Profil fuer die CI Maschine, eine fuer die Produktiv Umgebung.
Diese Properties per Environment sollten nicht mitgebundelt werden, sondern “extern” liegen.

Ansosnten kenne ich weder Ninja noch Teamcity :wink:

Nein, vorerst geht es nur um das Deployment der aktuellsten Version auf der selben Maschine, auf der der CI-Server läuft. Die Tests laufen derzeit ganz normal mit dem test-goal ohne weitere Plugins durch.

Cargo habe ich (mit gradle) schon benutzt und das läuft auch ziemlich einfach und reibungslos ab. Cargo kann man aber auch direkt vom CI-Server aus starten - das wäre also deiner Meinung nach vorzuziehen?
Mit Shell-Scripten könnte man problemlos die lokalen Prüfungen, ob die Anwendung läuft etc. machen. Man müsste auch vom uberjar nicht weg, sondern könnte das bisher erzeugte Artefakt nutzen. Auch ein “ordentliches” mit Stork erzeugtes Artefakt ließe sich problemlos entpacken / installieren / starten.
Triggern würde man das Script dann aus dem CI-Server heraus, wenn der Build erfolgreich abgeschlossen ist.

[quote=maki;115811]MIt dem Resource Filtering von Maven koennte ma so Properties auf Profilen einsetzen.
D.h. Standard Properties sind ohne Profil in der POM und beziehen sich per default immer auf DEV, also zB. eine H2/HSQL/Derby DB anstatt der echten (Postgres).[/quote]
Ich weiß zwar nicht, wie das geht, aber das hört sich zumindest sehr brauchbar an. Die maven-Doku hilft da bestimmt weiter.

Ich kann gerne auch statt dem TeamCity einen Jenkins aufsetzen. Ich hatte mich nur deshalb für TeamCity entschieden, weil es eine sehr gute Integration mit IntelliJ IDEA hat und ich damit schon ein bisschen herumgespielt habe. Jenkins hatte ich zwar auch kurz angetestet, TeamCity gefiel mir aber ein wenig besser, sodass ich dabei geblieben bin.

Shell Script.
Deployment ist ausserhalb des Build Prozesses, Maven hat da nicht seine staerken, Cargo etc. nutze ich am liebsten um Server fuer Integraiton stests aus dem Maven Build aufzuziehen (mit dem Failsafe Plugin).

Maven – Introduction to build profiles
Parent pom.xml:
[xml]
<project …>

<!--  default DEV values, ie. in Memory DB -->
<properties>
    <ninja.port>9999</nija.port>


<profiles>
    <profile>
            <id>ci</id>
           <properties>
               <ninja.port>6666</nija.port>





[/xml] Per default ist nija.port 9999, falls das CI Profil aktiv ist 6666.

Das geht eben auch fuer die DB Konfig unds alles moegliche.
Wenn man dafuer Properties einsetzt, kann man diese soghar von der KOmandozeile ueberschrieben (-DpropertyName=propertyValue)

Profile aktiviert man zB. per settings.xml, Kommandozeile oder durch aktivate Regeln.

Hab kein Problem mit TeamCity, muss mich halt nur reinarbeiten.

Wie man die Konfiguration extern laesst muss wohl bei Ninja beschrieben sein.
Ist wichtig, sonst muss man entweder das Artifakt (jar) aendern falls die Konfig angepasst werden muss oder ein neues Artifakt erzeugt werden… :frowning:

Die Ninja-Konfiguration kann man gemäß Doku über eine Property ninja.external.configuration verfeinern. Diese externe Konfigurationsdatei überschreibt, wenn ich die Doku richtig verstanden habe, die interne Konfiguration nur in den angegebenen Werten, sodass die externe Konfiguration recht schlank bleiben könnte.
Im TeamCity kann man maven problemlos weitere Kommandozeilenoptionen mitgeben. Da könnte man dann das Profil bspw. mittels -p ci-nightly auswählen.

*** Edit ***

Ein Shellscript zu starten ist kein Problem, dafür gibt es einen eigenen Runner in TeamCity, den man dann ausgeführen lassen kann, wenn alle vorherigen Schritte erfolgreich waren. Diesem Script kann man (variable) Kommandozeilenparameter mitgeben, wie beispielsweise den Pfad zum Artefakt, das deployed werden soll.

Sieht für mich so aus, als wenn damit das Handwerkszeug für ein automatisches Deployment zusammen wäre :slight_smile:

Hi,

habe mal den Build angeschaut und mir ist das hier aufgefallen:


...-B clean compile test assembly:single 

Das macht schlicht keinen Sinn…

  1. -B clean test
    reicht völlig aus, da der Life Cycle entsprechend die Phase Compile entsprechend abarbeitet…wenn man mvn clean compile test läuft die Compile Phase zweimal…

  2. Um ein Assembly zu bauen sollte man das in den Life Cycle entsprechend einbauen damit man im Build einfach mvn -B clean package machen kann…

Gibt es den Code irgendwo auf Github etc. ?

Gruß
Karl Heinz Marbaise

@kama : danke für die Hinweise. Ich habe die compile-Phase herausgeschmissen.

Den Code kannst du hier finden: https://github.com/fjorum/fjorum

Besser waere IMHO:
mvn clean verify

Dazu sollte das single Goal des Assembly Plugins an die package Phase gebunden werden:
[xml]

maven-assembly-plugin
2.5.3


jar-with-dependencies



ninja.standalone.NinjaJetty





make-assembly
package

single




[/xml]
Damit wird die Jar jedesmal in der package Phase erzeugt.

Das war es was kama meinte :wink:

Sieh dir mal den default lifecycle fuer Jar Projekte an:
https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference

Man bindet Plugin Goals an Lifecycle Phasen (hier eben package), damit wird dieses Plugin Goal (single) in dieser Phase von Maven aufgerufen.

Mehrere Phasen in der Kommandozeile anzugeben fuehrt dazu, dass der Lifecycle mehrmals durchlaufen wird, das verlangsamt den Build und verschleiert u.U. wenn Proejkte “kaputt” sind, hatte erst wieder so einen Fall in dem die generate resources explizit aufgerufen werden musste vor dem package, Ergebniss: Projekt kaputt :frowning:

Das hatte ich auch schon ausprobiert - deshalb habe ich das Projekt heute auf github geforkt :wink:
Das Problem ist, dass aus einem Grund, den ich noch nicht herausgefunden habe, die war, die in der package-Phase erzeugt wird, in die jar entpackt wird. Das bedeutet, dass die jar dann doppelt so groß wird, wie sie sein sollte.

Hi,

Wie kommst Du auf eine jar? Das ist ein WAR Projekt womit ein WAR erzeugt wird?

Habe schon mal zwei PR erstellt…

Mit dem assemble-plugin wird eine jar erstellt, die einen eingebetteten Jetty einbindet.

Das Problem ist, dass das maven-assembly-plugin nicht im Life Cycle gebunden. Das hat mich verwirrt… Das Problem mit den doppelten Libs (jar files) liegt einfach daran, dass das WAR eingebunden wird. Hier kommen wir zu dem Problem, zwei Sachen nicht in einem Module zu machen (Separation of Concerns). Besser wäre hier ein Module für die Erstellung des WAR’s zu machen und eines für die Erstellung des JAR’s…

Das ist der Grund fuer das WAR:
[xml]war[/xml]
Wenn man kein WAR sondern nur eine JAR braucht, dann Packaging weglassen (default ist jar) oder explizit jar setzen.

Wenn man beides braucht gibt es auch Wege dahin…