hudson

Command line CI

Friday, September 17th, 2010 | Uncategorized | No Comments

Az elmúlt hetek legjobb híre az volt, hogy megjelent az Amazon EC2 gépek közül a micro méret. Ebben csak 600 MB memória van viszont az ára is ehhez van mérve (2 cent/óra). Ez már elég kedvező, gyakorlatilag pár ezer forintért lehet futtatni teljes értékű szervert.

Jelen blog is éppen egy AWS példányon fut valahol a tengeren túlon (ezt persze az éles szeműek nyilván észrevették az IP címváltozásból is).

A 600 MB viszont bölcs takarékosságra neveli az embert. Apache Httpd helyett lighthttpd + mysql + alaprdendszer, ez körülbelül 100-150 Mb-t eszik. Egy Hudson körülbelül ugyanennyit alapjáraton, de azt gyanítom a pluginekkel és projektekkel még hízik.

A Hudson amúgy szerintem az egyik legjobb Java-s alkalmazás. Nagyon sok részéről süt, hogy ezt használatra találták ki. Pl. webes felületen keresztül frissíthető, telepíthető bele plugin. Tisztára mint egy jó értelemben vett termék.

A 600 MB memóriámnak a negyedét viszont lehet, hogy sajnálnám tőle. Elkezdtem gondolkozni egy command line CI szerveren. A cron töltené be az ütemező szerepét az hívna meg valamilyen (script?) nyelven implementált kis belső magot, ami ellenőrizné, hogy van-e változás az SCM-ben, és ha van elindítaná a fordítást. A fordítás eredményéről értesítéseket küldene, és statikus HTML oldalakat generálna. Végül is a buildek eredménye bőven elég statikusan.

Eddig (kis keresgélés után) találtam is egy ehhez hasonlót Cerberus néven. Igaz egyelőre elég alap funkcionalitással bír, pl. HTML oldalakat nem generál, csak értesít, de talán kiindulásnak jó lesz. Forkolni kéne egy üres órámban.

Tags: , , ,

Maven, Release, Hudson

Tuesday, July 27th, 2010 | Uncategorized | No Comments

Az ideális releaselés minimum követelményeit így képzelem:

  1. A release automatikus (egy gombnyomásra történik) és a CI szerver készíti el
  2. hiba esetén újra lehet indítani
  3. nem befolyásolja közben a fejlesztést (nincs commit csönd)

Alapvetően sose voltam nagy barátja a Maven release pluginnek, kicsit merevnek tartottam, de hosszas kísérletezés után legtöbb esetben még mindig ez tűnt a legkevésbé problémás megoldásnak. Kicsit kell figyelni a pom-ok felépítésére, de az még jó is, ha tisztább pomokra kényszerít. (Egyébként a forrása is viszonylag kellemes csalódás volt, egész szép, leszámítva a modellos fejlövéstől, amit az előzőekben már felhánytorgattam).

Ha a maven release plugin már adott mint eszköz, akkor még mindig van néhány nyitott kérdés:

1. trunkon vagy branchen?

A kedvenc koncepcióm a tárgyban itt olvasható. (Git-ről beszél, de Mercuriallal ugyanúgy használható). Ez egyértelműen azt javasolja, hogy külön ágon releaseljünk. Ez egy kicsit megbonyolíthatja a release folyamatot, de amellett előnyei is vannak:

  1. a hármas pontot alapból kielégíti. A release branchre rámergáljuk a trunkról a stabil változatot, és release közben már senki se ronthatja azt el.
  2. lehetőség van arra, hogy ne csak a trunk ágat, hanem más ágakat is releaseljük. Ha egyszer a release ágon működő release-gép tökéletes, akkor csak azt kell elérni, hogy bárhonnan a release ágra mergeljünk bármilyen kódot (akár egyoldalú merge-vel, ahol minden fájlból a külső branchen lévő változatot tekintjük alapnak).

A .2 pont persze már eltér a fenti linken található ábrától, amely ábra külödben sem is használható tisztán maven release pluginnel, mivel pl. a tagelést a plugin egyértelműen a release branchen végzi. A 2-es pont szerint a release branchünk igazából csak egy staging hely, ahová felrakhatjuk a kódot, amíg a release sikerül, és a mikor ténylegesen kész lesz, akkor vissza mergelhetjük.

2. külön release job a hudsonban vagy nem?

Ha használjuk a trunk mellett a release branchet is, akkor rögtön jön a probléma, hogy a hudsonon alapból a trunk branchet akarjuk buildelni, de releasekor a release branchet. Ezt a hudson egy kicsit nehézkesen kezeli. Léteznek workaroundok: pl. m2 extra stepst-ben hg parancsok, vagy paraméterezett build, ahol a paraméter alapján checkoutol, de a gyakorlatban nekem egyik se bizonyult stabil megoldásnak (az átláthatóságról nem is beszélve).

Az egyszerű megoldás, amit épp követünk, új jobot hozunk létre a Hudsonon. Klónozzuk az eredetit, és az új job az előzőekkel megegyezően működik (változás esetén sajnos mindig frissíteni kell a build paramétereket), de a release branchet forgatja (célszerűen private local maven repository-t használva!!).

A külön job-os megoldás arra is jó, hogy a release branchre való merge után még egy utolsó ellenőrzésként egy hagyományos buildet is kérhetünk az ágra, mielőtt a release build-et kérjük a hudsonból

3. M2 release plugin vagy általános release plugin?

A Hudsonban két release plugin is van. Egy általános és egy kifejezett Maven-re szabott. Mindkettő azt nyújtja, hogy megjelenik egy új gomb is a job oldalán: a build now mellet lesz egy start release build opció is.

Az általános release pluginban  pre-steps és post-steps lehetőségek vannak. A release build gyakorlatilag egy rendes build, csak a post f’ázisban tetszőleges múveleteket (pl. release:prepare release:perform) is elvégezhetünk. Sajnos a Hudson korlátai miatt a post lépések mindenképpen lefutnak még akkor is, ha a rendes build elhalt, ami nem túl elegáns.

Az általános release pluginnak viszont kellemes szolgáltatása, hogy a release buildet tartóssá teszi (keep this build forever) és meg is tegeli. Így a job lefutásai között egyértelműen látszik, hogy melyik volt a release.

Egyelőre én mégis a Hudson M2 release plugint használom. Ez kifejezetten Maven releasere lett kitalálva, tehát korlátozottabb tudású, azt viszont jól csinálja, és nem kell trükközi post stepekbe rejtett release logikával. A sikeres release buildet aztán kézzel tartosítom (keep build forever).

4. staging scm vagy éles?

Az egyik problémája a release pluginnek, hogy elosztott SCM esetén nem csak commitol, hanem pushol is. Ha a release mégsem sikerül, akkor is teleszemetelte a repónkat mindenféle saját committal. Erre ad egyfajta megoldást Fabrizio Guiduci. Ennek lényege, hogy a release alatt egy profile/property trükkel az aktuális scm bejegyzést egy temporáls repositoryra állítja át, így oda fog pusholni a release plugin. Amennyiben a release sikeres volt, akkor a staging repositoryból lehet pusholni az élesbe.

Volt, ahol használtam ezt a trükköt, de ma már úgy látom, hogy nincs nagy jelentősége. Egyrészt mivel külön release branchen releaselek, ott nem zavarnak a felesleges commitok annyira. Legrosszabb esetben hg backout-olok (remek parancs, egy adott commit diff-jét invertálja és commitolja újra be.) Git-be meg ugye alapból lehet changeseteket törölni.

Másrészt mivel a Hudson-on a release branchre rá van állítva a release job, amit release előt még sima buildel ellenőrzök, az esetek nagy részében a releasenek már hiba nélkül kell lemennie. (Általában hiba ebben a fázisban már csak akkor merült fel, ha pont a pusholás volt sikertelen)

5. staging repo vagy éles?

Az előbbi linken nem csak a mercurial repositoryból csinált stage-et az író, hanem a cél Maven repositoryból is. Kezdetben csak egy temporális helyre deployolt, és ha minden jól ment, akkor onnan egy maven pluginnel tolta fel a végleges helyére a buildelt artifactokat.

(Egy kicsit kidolgozottabb staging koncepció is létezik, amit a Nexus Pro támogat.)

Eddig az volt a tapasztalatom, hogy ilyenek nélkül elég jó tudok élni. A deploy a release:perform utolsó lépése, tehát ha felmentek az artifactok, akkor a release már jó volt, ha nem ment fel, akkor még gyűrni kell. De olyan eset eddig nem volt, hogy felment, de le akartom volna szedni.

Egyéb tapasztalatok

1. A maven release plugin nem szereti, ha elosztott verzió kezelőt használunk és nem a gyökérben van a pom.xml. A release:perform lépésben ugyanis a target/checout könyvtárba az egész repót klónozza, de arra nem lehet rávenni, hogy a repó egy alkönyvtárát buildelje csak meg. Botrány.

2. A release:prepare lépés során történik egy ellenőrzés. A checkoutolt source-on a maven futtat egy clean verify kombót. Ez kellemetlen meglepetésekkel szolgálhat, ha az alprojektek kézileg össze vannak kötögetve. (Pl. dependencies:unpack). Ekkor a nagyerejű -DpreparationGoals=”clean install” segíthet.

A többi meg már megy magától.

Tags: , , ,

Meta

Search