15 Nisan 2014 Salı

Apache Tomcat & Jenkins

CI server olarak kullanacağımızı belirttiğimiz Jenkins aracı java dilinde geliştirilmiş ve sitesinde hem kurulum şeklinde bir paketle hem de war (Web Archive) dosyası olarak yayınlanmaktadır. Biz sürecin tamamına hakim olmak her istediğimizi tune edebilmek istiyoruz bu sebeple war paketi ile çalışacağız. Web arşivi ile çalışacaksak bu web arşivini deploy edebileceğimiz bir sunucu yazılıma ihtiyacımız bulunmaktadır. Burada en kısa yoldan bize çözüm sunacak Apache Tomcat i tercih ediyoruz.

Ön gereksinim olarak Java run time ihtiyacımız olacak onu da bu linkten indirebilirsiniz. Linkte server jre paketleri bulunmakta. Bu paket hem jre içermekte, hem de Java uygulamalarınızı takip edebileceğiniz monitör uygulamaları gibi bazı araçları da içermektedir. En önemlisi production ortamlardaki can sıkıcı Java update özelliği gelmiyor bu pakette. 

1. Java Run Time Kurulumu:
  1. Daha önce indirme linkini verdiğimiz dosyanın uzantısı tar.gz'dir. Winrar ile açıldığında direk olarak karşınıza jdk1.8.0 dizini çıkacaktır. 7.zip ile açtığınızda içerisinde .tar uzantılı bir dosya görünecektir, onu da 7zip içerisinde iken çift tıklarsanız jdk1.8.0 dizinini göreceksiniz.
  2. Bu dizini CI_Working_Engine klasörü altına aynen koyalım.
  3. Ardından Windows'da Control Panel --> System and security --> System --> Advanced System Settings altında Environment Variables dialogunda yeni bir sistem değişkeni tanımlayalım. Girilecek değerleri aşağıdaki şekildeki gibi uygun olacak şekilde girelim.
  4. Tamam deyip çıktığımızda artık Java uygulamalarının Java kurulumu nerede diye aradığı JAVA_HOME değişkeni set edilmiş olacak.
Java uygulamalarımız için Java kurulum dizinini bir sistem değişkeniyle belirtiyoruz
Notlar:
  1. Aşağıdaki komut satırı işlemlerini admin hakları ile yapmanız gerekmektedir. Servis kurma kaldırma gibi işlemler nedeni ile bu şart. Bu sebeple komut satırını "Yönetici olarak aç (Run as admin)" seçeneği ile açmalısınız. Aksi takdirde ya işlemleriniz olmayacak ya da oldu gibi görünen işlemler hata vererek başınızı ağartacaktır.
  2. Kurulumlara başlamadan önce rahatça log ve konfigürasyon dosyalarını incelemek-karşılaştırmak için Notepad++ ve ardından compare plug-in ini kurmanız sizi rahatlatacak ve de size zaman kazandıracaktır. Zira bu tip text dosyaları ile artık çokça haşir neşir olacaksınız. Plug-in dosyasını manuel kuracaksanız sadece dll dosyasını Notepad++ kurulum dizinindeki plugins klasörüne atmanız yeterli. Build makineniz internete açıksa zaten online olarak notepad++ plugin manager menüsünden istediğiniz eklentiyi kurabilirsiniz.

2. Apache Tomcat Kurulumu:
  1. Adresinden 64 bit Windows zip olan sürümü indirelim.
  2. CI sunucusu olarak belirlediğiniz bilgisayarda bu dizini açalım. Mesela bu dizin E altında CI_Working _Engine dizini olsun. (Anlaşılabilir olsun diye kendi dizin yapımı örnek olarak alacağım)
  3. Komut satırında E:\CI_Working_Engine\apache-tomcat-8.0.5\bin\ adresinde iken startup.bat dosyasını çalıştırdığımızda JAVA_HOME veya JRE_HOME adreslerine sahip olmadığımızı belirten bir hata alabiliriz. Java run-time kurulumunu bir önceki adımda yapmıştık.
  4. Java kurulumundan sonra tekrar denediğimizde (yeni komut satırı penceresi gerekli) aşağıdaki ilk pencerenin Tomcat i çağırıp ikinci bir komut satırında çalıştırdığı görülür. (Çalıştığını görmek için, ilerleyen bölümlerde bulunan chrome ekranındaki gibi, tarayıcı ile de 8080 port kontrolü yapılabilir, tabii sağ tarafta log bilgileri ile birlikte görünen Tomcat konsol sürekli açık olmak zorunda)
Tomcat uygulama sunucumuz konsoldan da olsa çalışıyor
Pratik Notlar:
Gerçekten bir CI sistem kuruyor isek yapmışken düzgün yapmalıyız. Öyleyse Tomcat bu şekilde elle manuel değil, Windows servisi olarak otomatik ayağa kalkabilmelidir. Tomcat penceresinde iken ctrl + c yapıp sunucu uygulamamızı kapatalım ve yine komut satırında bin klasörünün altındaki "service.bat" şeklindeki bat dosyasını aşağıdaki resimdeki gibi install seçeneği ile çalıştıralım.
Tomcat uygulama sunucusunu servis olarak kurma

Anlayacağınız üzere Tomcat i servis haline getiren komutlar service.bat dosyası içerisinde saklı. Biraz vakit ayırıp kurcalarsanız servis adı, install, uninstall gibi çalıştırma şekillerini dosya içerisinde bulabilirsiniz. Yukarıdaki işlemin ardından Windows servis listesini kontrol ederseniz ("services.msc"), görünür ismi "Apache Tomcat 8 Tomcat 8", servis adı "Tomcat 8" olan servisimizi görebilirsiniz.

İp ucu 1: Windows'da bir servis silmek için komut satırında "Sc delete servis_adı" komutunu kullanabilirsiniz. Servis adını da, Windows'da ara menüsüne "services.msc" komutunu yazarak çalıştırıp, ilgili servise çift tıkladığınızda erişebilirsiniz.

İp ucu 2: Yeri burası diye söylemiş olalım. Oluşturduğunuz bu Tomcat 8 servis altında deploy edeceğimiz herhangi bir uygulama (Biz jenkins deploy edeceğiz) network üzerinde her hangi bir makineye erişmesi gerekirse, bir yere bir dosya yazması gerekirse otantikasyon olarak, servisi çalıştıran login bilgilerine göre otantikasyon yapacaktır. Yani bir domainde iseniz ve bir kullanıcının bu yazacağınız adres veya erişeceğiniz makineye erişim yetkisi varsa, erişimi sağlamak adına servisi bu kişinin login bilgileri ile başlatmanız gerekir. Aksi takdirde servis çalışır fakat Tomcat log dosyalarında "Access Denied", "No permission" vs. yetki hataları aldığınızı görürsünüz. Servisi erişime yetkili kılmak için "services.msc" açıldıktan sonra "Apache Tomcat 8 Tomcat 8" servisimize çift tıklayın ve log on sekmesindeki "This account" kısmına yetkili kişinin (domain kullanıcıları da dahil) giriş bilgilerini girin. Varsayılan olarak lokal makinenin sistem hesabı çalışıyor, fark etmişsinizdir. Bu anlattığım erişim bilgisi şu an için gereksiz gibi dursa da; ileri de CI sisteminiz ayağa kalktıkça bu gereksinim karşınıza eninde sonunda çıkacaktır. Zira tüm kaynaklarınızın build makinesinde lokal olarak bulunabileceğini sanmıyorum. Mesela kendi örneğimizde, Jenkins ağda farklı bir yerlere erişmeye kalktığında (kuracağınız farklı eklentiler bunu yapmak isteyebilir) eğer Tomcat servisimiz yetkisiz bir kişi ile başlatılmışsa hata almamız kaçınılmazdır. Erişim mevzusu ile alakalı Jenkins için yazacağınız ANT scriptleri için de "SSH" bağlantı kurma konusu var ileride yeri gelince onu da anlatacağım. Kısacası SSH size iki makine arasında güvenli ve yetkilendirilmiş bir bağlantı kurmanıza yarar, böylece SSH destekli script kodlarınız ile farklı makinelerde yetki gerektiren işlemleri yapabilirsiniz. Diğer bir husus da servisi çift tıkladığınızda "Startup-type" olarak görünen kısmı da otomatiğe çekerseniz build makineniz kapanıp açılsa dahi servis otomatik çalışacaktır ki zaten böyle olmasını istiyoruz. Bunlar pratikte gerçek bir CI sistem için ufak ama karşınıza çıkacak önemli noktalardı.

Servisler penceresinde iken sağ tuş start dediğinizde Tomcat servisimiz başlayacaktır. Kontrol için bir web tarayıcı ile 8080 (Tomcat default port) portunu kontrol edebilirsiniz.

Tomcat uygulama sunucumuz çalışıyor hem de Windows servisi olarak !


Tomcat çalışırken oluşan log dosyalarını Tomcat çalışma dizinindeki logs klasöründe bulabilirsiniz. Buradaki "Catalina_tarih.log" dosyasını inceleyebilirsiniz, genelde incelenen temel log dosyası kendileri oluyor.

Tomcat Yetkilendirme Mekanizmasını Kurma
Gerçekten bir CI sistemi ayağa kaldırmayı hedeflediğimize göre uygulama sunucumuzun yetkilendirme mekanizmasını kurmamız gerekli. Tomcat varsayılan olarak yönetim ekranlarına erişimi kapalı olarak gelmektedir. Örnek vermek gerekirse yukarıda chrome ile görüntülenen Tomcat ana ekranında sağ tarafta bulunan Manager App butonunu tıkladığınızda sizden login bilgisi isteyecektir. Fakat ne yaparsanız yapın ne girerseniz girin kaçınılmaz olarak aşağıdaki ekran ile karşılaşacaksınız.

Tomcat yetkilendirme mekanizması henüz kurulmamış
Bu ekran bize aslında ilk defa kurulum yapanların Tomcat'de credential bilgilerini nasıl konfigüre edeceğimizi yazılı olarak belirtiyor. Biz de aynen yazılanlar gibi Tomcat çalıştırma dizininde conf klasörü altında bulunan "tomcat-users.xml" dosyasını Notepad++ ile açalım ve eklemelere başlayalım. Tüm yorum satırları aynen kalsın, tomcat-users etiketleri arasına aşağıdaki aşağıdaki eklemeleri yapalım:

<role rolename="manager-gui"/>
<user username="admin" password="admin" roles="manager-gui"/>

Bu şekilde bir kullanıcı adı ve şifre belirlemiş olduk ve bu kullanıcıya Tomcat için tanımlı rollerden birini atamış olduk. İstediğiniz kullanıcı adı ve şifreyi belirlemek size kalmış.

Artık Manager App butonuna tıkladığımızda karşımıza çıkan login ekranında admin / admin bilgilerini girdiğimizde karşımıza aşağıdaki ekran çıkacaktır. Bu da Tomcat'de yetkilendirme kısmını temel de olsa çözdük demektir.

Tomcat Manager App ekranı







3. Jenkins Kurulumu:
  1. Adresinden Latest and greatest yazan war paketi versiyonu indirelim. (Şu anki güncel versiyon 1558)
  2. Tomcat servsimizi durdurup, bu war dosyasını Tomcat klasöründe bulunan webapps klasörüne koyalım, Tomcat servisimizi başlatalım hepsi bu :)
  3. Web tarayıcımızda localhost:8080/jenkins adresine bakarak Jenkins aracımızın çalıştığını görelim.
Jenkins ana ekranı

Bir sonraki yazımızda Jenkins sürekli entegrasyon sunucumuzu inceleyip konfigüre edeceğiz.





9 Nisan 2014 Çarşamba

Jenkins mi Hudson mı?

Perde Arkası
Aslında bu konu biraz sonra yazacaklarımdan anlaşılacağı üzere mazide kalmış ve cevabı az çok belli olan bir konu. Yazmamın tek sebebi Hudson aracının (Resimde görüleceği üzere Eclipse i arkasına da almış amcamız) hala farklı bir şekilde hortlatılmaya çalışılmasından kaynaklanmakta. Hikayeyi John Ferguson Smart'a ait "Jenkins: The Definitive Guide" adlı kitabından tercüme ederek biraz da ekstra bilgi katarak yazalım: (Sayfa 3 Bölüm 1.4)
"Koshuke Kawaguchi SUN'da çalışırken 2004 sonlarında tamamen hobi amacıyla Hudson adlı bir projeye başlar. Tabii proje geliştikçe gelişir ve artık SUN kendi iç projelerinde bu aracı kullanmaya başlar. Bu aracın değerini anlayan SUN 2008 başlarında Koshuke'den sadece Hudson projesine yoğunlaşmasını ister ve projeyi hobi olmaktan çıkartıp, kendisine profesyonel bir şekilde katkı ve destek sağlar. 2010 yılında artık Hudson pazarın %70'ine hakim olan lider sürekli entegrasyon aracı haline gelir.

2009 yılında Oracle SUN'ı satın alır. 2010'un sonlarına doğru Hudson geliştirici topluluğu ile Oracle arasında bazı gerginlikler baş gösterir. Bu gerginliklerin temel nedenleri olarak Java.net infrastructure'daki bazı problemler ve Oracle'ın Hudson'ı markalaştırma istekleri gösterilir. Bu gerginlikler tabii Oracle yönetimindeki projenin işleyişini de bayağı bir etkiler. Şöyle ki; Oracle release takviminin yavaş olduğu çok sıkı kontroller altında geliştirilen bir geliştirme süreci öngörürken, Koshuke liderliğindeki geliştirici ekip eskiden Hudson'da başarıyla uyguladıkları gibi açık kaynak kodlu, esnek, hızla yapılan, community odaklı bir geliştirmeden yanadır. Kasım 2010'da Oracle ürün yöneticisi Susan Duncan tam bu ayrım noktasında iken insanları Oracle arkasında durmaya devam eder bu durumu da bu forum sayfasında belirtir. Hadi herkes bizim projeye dediği günün üzerinden fazla geçmeden Bu sitede Oracle artık bu işi yürütemeyeceğini anlar ve sayfanın forum sitesinde kullanıcıları başka bir mecraya doğru sürüklediğini belirtir.
Ocak 2011'de Hudson geliştiricileri son derece kararlı bir şekilde projenin adını Jenkins olarak belirler ve Hudson kodlarını yeni bir GitHub projesine alarak çalışmalarına buradan devam ederler. Çekirdeği ve eklentileri yazan çoğu geliştirici Koshuke'yi takip edip Jenkins topluluğunu böylece oluştururlar. Koshuke aldığı bu kararı kendi blog sitesinin bu sayfasında yayınlar ve kendi adını koyduğu ve büyüttüğü projesine güle güle Hudson demek zorunda kalır ya da bırakılır diyelim.
Bu çatallanmadan (Project Fork, versiyon 1.395 den sonra ) sonra kullnıcıların da bayağı bir kısmı Jenkins tarafına geçer. Kitabın yazım tarihinde (2011) kullanıcıların %75'i projelerini Jenkins'e taşımış, %13 Hudson'da kalmış, % 12 ise her ikisini de kullanır halde Jenkins'e geçmeyi planlamaktaymışlar.
Ama gelin görün ki hal böyleyken Oracle ve Sonatype (Maven ve Nexus'un arkasındaki firma) Hudson üzerinde çalışmalarına Github üzerine de taşıyarak halen devam ederler. Ama odaklarını altta yatan infrastructure, Maven entegrasyonu, dependency injection framework ve eklenti mimarisi gibi farklı konulara kaydırmış durumdadırlar." 
Olayı kaldığı yerden ben devam ettireyim. Oracle her ne kadar projeyi devam ettirmeye çalışsa da yürüttüğü projeleri hep atıl kalır.  Kitabın basım tarihinden çok sonra, 24 Ocak 2012 günü Oracle Hudson projesini tamamen Eclipse vakfına devreder ve projenin adı Eclipse Hudson adıyla halen devam ettirilmektedir. Koshuke'nin ve topluluğun Jenkins hamlesinin ve Oracle'a karşı olan davranışının ne kadar doğru olduğu da böylece bir nebze anlaşılmış olur.

Hangisini Seçmeliyim?
Eveet, Smart'a bu bilgileri sağladığı için çok teşekkür ederek biz neyi seçelim sorusuna cevap arayalım. Efendim; Hudson bir CI sisteminiz varsa, güncellemek ve yeni versiyonlara geçmek istemiyorsanız, yeni özellikler benim neyime diyorsanız, eğer çalışıyorsa tamir etme mantığı (If it works Don't fix it !) ile hareket ediyorsanız, Sonatype'ın ileride getireceği standart eklenti geliştirme yöntemi ile kendi eklentimi kendim daha kolay yazarım diyorsanız, Hudson ile mutlu mesut yola devam etmelisiniz, sizin için yapılabilecek pek bir şey yok. Hudson'un geleceği için ise, Eclipse projesi olması dolayısı ile IDE entegrasyonu, diğer Eclipse eklentileri ile entegrasyon vs gibi konulara kapı aralanmış durumda, göreceğiz bakalım ama ortada henüz net bir şey yok bu konuda.

Yok ben yeni Hudson'ı kullanacağım derseniz, topluluğun gücünü arkama alacağım derseniz, bir hatayı hep benden önce bulup çoktan raporlamış ve yeni sürüme çözüm olarak ekletmiş bir toplulukta yaşayacağım derseniz, hem hızlı geliştirilen (haftalık) hem de uzun dönemli (3 haftalık) daha stabil versiyonları olan bir CI sunucu programım olsun derseniz, olursa son model olsun derseniz, buyurun size taze taze mis gibi Jenkins verelim :)

Karar Vermeye Yardımcı Olalım
Yazıyı yazıyor olduğum şu ana (15.04.2014) ait, güncel GitHub istatistiği vererek seçiminize yardımcı olalım: 
Jenkins : 569 üye, 1191 depo.
Hudson:   32 üye, 17 depo.

Hudson forumlarında dolaşırsanız "bazı eklentilerin hala neden güncellemediğini ama Jenkins'inki niye güncel :( " gibi yazılara denk gelebilirsiniz :) Bunun yanında bunu yazanların "yanlış anlamayın ben Hudson kullanıyorum ileride de kullanmak istiyorum, güvenlik, stabilizasyon vs benim için önemli" dediklerini de görebilirsiniz.

Ayrıca burada CI server ile ilgili bir oylama bir şeyler ifade etmesi açısından önemli. Hiç bir şey kullanmayanlara mı yanalım ne yapalım bilemedim :(

Koshuke de kendi web sitesinde Jenkins ve Hudson üzerindeki commit sayılarını 2012'de yayınlamış işte link. Sayfanın başında dış bir link ile 2012-2013 arası istatistik de var.

Bu da Koshuke ile Oğuz Dağ arasında geçen söyleşi. Tabii Koshuke'nin o zamanki düşünceleri biraz farklı imiş Hudson ile ilgili, henüz ayrılık olmamış. Ama arkadaştaki motivasyona, hem de open source bir projede, 
hayran olmamak elde değil.

Bu linkte InfoQ firmasının yapmış olduğu bir anketi görebilirsiniz. İnsanlara hangi CI sunucuyu kullandıklarını soruyorlar. Jenkins burada da açık ara önde gidiyor. Ben de sağ tarafta devamlı açık bir anket tutmaya başlamıştım. Benim de anket listeme koyduklarım isabet olmuş, InfoQ sıralamasında neredeyse en çok kullanılanları tutturmuş ve listeye yazmışım :) "Vote Now" açıkken oyunuzu vereceğiniz aracı sürükleyip grafikte uygun yere bırakın sonra "Submit Vote" deyin sonra sonuca bakın. Direk sonuç için "Average" butonunu kullanabilirsiniz. Jenkins yaklaşık %75 oy almıştı ben bakarken, yorum sizlerin...

Her iki araç da en azından şu an için görüntü olarak birbirine çok yakın durumdalar. Birine aşina iseniz diğeri size aynı gibi gelecektir, bu bilgiyi de verelim ve her iki proje özelinde bir şeyler de yazarak bu konuyu kapatalım.

                                                         Jenkins
Bıyık altından Hudson'a gülüş
Biraz Java dünyasının konu ile alakasına değinelim. John Ferguson Smart, Wakeleo Consulting firmasında kurumsal Java ve Agile yöntemler hakkında danışmanlık veren ve Java yazılım çevrelerince tanınan meşhur bir kişi. Yazıları, kitapları son derece pratik ve bilgi dolu oluyor. Siz de internetten ilgilendiğiniz konularla alakalı sunumlarını, yazılarını bulabilirseniz kesinlikle okumanızı tavsiye ederim, çok faydasını görürsünüz. Bu adresten Smart'ın Jeknis ile ilgili hazırlamış olduğu elektronik bir kitabını ücretsiz indirebilirsiniz. Çok güzel bir şekilde CI mantığının Jenkins özelinde, bir organizasyona nasıl fazlar halinde entegre edileceği detaylıca anlatılmış. Bir kere olsa içindekiler listesine bakıp ilginizi çeken kısımlara göz gezdirmenizde çok fayda var.
Smart'dan laf açılmışken ayrıca Java dünyasında yaşayanlar için 912 sayfalık java power tools adlı kitabı, java proje liderleri için tam bir başucu kitabı niteliğinde. Bu kitabın ne yazık ki ücretsiz bir versiyonu yok. Sürekli entegrasyonun araçlar ile birlikte baştan sona anlatıldığı bir kitap.

Jenkins'e dönecek olursak; Jenkins haftalık sürüm çıkarması ile iştahlı kullanıcılarını mest etmeye devam ederken, kararlı sürüm seven daha durağan kullanıcıları için ise 3 haftalık periyotlar halinde "older but stable" mantığı ile long term support versiyonu çıkarmaktadır. Bu durum stabilizasyon arayan Hudson kullanıcılarının Jenkins'e geçmesine en büyük nedeni olarak gösterilebilir. Çünkü zaten kapalı bir ağda iseniz ki azımsanmayacak kadar proje bu şekilde çalışıyor gördüğüm kadarı ile, güvenlik konusu pek dert edeceğiniz bir durum olmayabilir. 

Hudson
Hudson için size sitelerini vermekten öte çok bir şey sunamayacağım zira hem kullanmıyorum hem de pek kullananı görmedim etrafımda. 

Bu site Oracle tarafından yayınlanan web sayfası. Bu da Eclipse vakfı tarafından sürdürülen site. Eclipse vakfının sayfasında yukarı menüde bulunan "About this project" linkine tıkladığınızda commit sayılarını (ve azlığını) göreceksiniz. "Who's involved" menüsünde ise projeyi ilerletmeye çalışan ekibi göreceksiniz. Daha detaylı bilgileri kurcalamayı size bırakıyorum, zira siz bakıyorken bir çok şey değişmiş olabilir bu proje ile alakalı. İnternette biraz araştırınca sizin de hemen karşınıza gelecek olan içerik eskimiş olsa da eskiye ait geçerli bilgileri bulundurduğunu düşündüğüm bu site var. Belki eski versiyona eklentilerden vs. den dolayı bağımlılığı olanlar vardır, onların işine yarar. İyice eski olan Hudson üzerinden anlatılıyor, bir kere okunmasında belki genel olarak da fayda da var. 

Bir sonraki yazımızda Apache Tomcat kullanarak, seçmiş olduğumuz Jenkins CI sunucumuzu ayağa kaldıracağız.

Konu ile ilgili başkaca linkler:
Jenkins (Community) & Hudson (Sonatype - Oracle) Hikayeleri

3 Nisan 2014 Perşembe

Sürekli Entegrasyon


CI sistemlerde işleyiş mantığı,
Tıkır tıkır çalışmak
Orta ve büyük yazılım projelerinin kaçınılmaz ögelerinden biridir sürekli entegrasyon. Ayrıca agile süreçler içerisinde de olmazsa olmaz bir kavram olarak göze çarpmaktadır. Bu yazı dizisinde Sürekli entegrasyon detaylarına, teorisine çok derinlemesine girmeyeceğim daha çok neden gerekli olduğunu ortaya koyup pratik olarak nasıl hayata geçirebiliriz gibi konuları ele almayı düşünüyorum. Şimdiye kadar nette bulduğum bilgileri sizinle paylaşayım ki vakit kazanalım: Oğuz Dağ kendi bloğunda iki yazı dizisi halinde (Bir ve iki) konuyu ele almış. Özcan Acar Bey zamanında sitesinde yeterince anlatmış öyle ki kitap bile hazırlamış bunun için biraz eskimiş ama olsun temeller aynı. Kodcu.com'dan Rahman Usta'nın da bu videosu diğer güzel bir kaynak. Güncel bir kaynak olarak Berat Doğan'ın bloğundan bu yazı da enterasan. Böyle online bir hizmeti yeni görüyorum. Bu da Cem Güler'in görüşlerini içeren bir yazı. İşin iyice temellerine ineceğim derseniz Martin Fowler ile sizi baş başa bırakabilirim.

Temel kavramları hemen bu sayfada anlayabilmek adına acm-software den bir alıntı yapalım, güzel özetlemişler:
"Continuous Integration (Sürekli Entegrasyon), bir yazılım takımının ürettiği kodun sürekli ve sorunsuz olarak sisteme entegre edilmesini amaçlayan bir sistemdir. Bu entegrasyon süreci, çeşitli araçlar ile otomatik hale getirilmekte ve belirlenen sürelerde çeşitli scriptler ve işlemler çalıştırılarak kodun sürüme uygunluğu sürekli olarak test edilmektedir. Böylece entegrasyon hataları mümkün olan en kısa sürede bulanabilmektedir. Ayrıca, repository de bulunan kodların belirli aralıklarla test senaryolarının koşturulması ile sistem tutarlılığı sağlanmakta, geliştirilen deployment otomasyonu ile deployment süreçlerinde, insan faktöründen kaynaklanabilecek hatalar en aza indirgenmektedir.
Sürekli Entegrasyonun bazı yararları şu şekilde de sıralanabilir: 
  • Hatalar hızlı bir şekilde bulunur ve çözüm süreci başlar, 
  • Yazılım ürününün durumunun metriklerle ölçülmesi kolaylaşır, 
  • Varsayımlar üzerinden değil, somut yazılım üzerinden test yapılması sağlanır,
  • Kişilerce tekrarlanmak zorunda olan süreçleri kısaltır ve otomatik hale getirir, 
  • Her an deploy edilebilen yazılım çıkarılabilinmesine olanak verir, 
  • Projelerde saydamlık artar, 
  • Yazılımcılara ve ürüne güven aşılanmış olur."
Bir diğer alıntıyı da prime teknolojinin bu sayfasından yapalım:
"Sürekli entegrasyon ekip üyelerinin birbirlerinin ayaklarına basmamaları için kullanılır. Projelerde fark edilmesi ve düzeltilmesi en zahmetli problemler entegrasyon problemleridir. Sürekli entegrasyon sunucusu ekibin yaptığı kod değişikliklerini versiyon kontrol sunucusu (örn Subversion) vasıtasıyla izler. Herhangi bir değişikliği gördüğünde entegrasyon kurulumunu başlatır. Bu kurulum projenin özelliklerine göre şekillenir fakat basitçe tüm kodlar derlenir, testler çalıştırılır ve sonuçlar yayınlanır. Eğer bir hata varsa kurulum kırılır. Bu durumda ekibin önceliği entegrasyon problemini çözmektir. Kurulumun kırılması üretim hattında problemin ortaya çıkması gibidir, şalter indirilir ve bozukluk tamir edilir ve üretim hattı devam eder. Kurulum kırılması ekibin verimliliğini negatif etkiler. Geliştiriciler bunu önlemek için yaptıkları değişikleri versiyon kontrole eklemeden önce son değişikleri alırlar, yerel bir kurulum yapıp sonuç başarılı ise kendi değişikliklerini versiyon kontrole eklerler. Kurulumlar tamamen otomatiktir ve kurulum süresinin 10 dk nın altında olmasına özen gösterilir. Büyük projelerde kurulumlar sürekli, gecelik gibi aşamalara bölünür. Sürekli entegrasyon kodların hatasız, her an kullanıma hazır tutulmasını mümkün kılar. Bir noktalı virgül dahi değiştiğinde kapsamlı testler değişikliğin etkilerini inceler ve problemler çıkar çıkmaz ekip tarafından düzeltilir. Sürekli entegrasyon ‘Benim makinemde çalışıyordu burada niye çalışmıyor’ problemini çözer."
Son bir alıntıyı da ekşi sözlükte gördüğüm whisky adlı kullanıcıdan yapalım:
"Yazılım geliştirirken geliştirmenin her aşamasında projeyi çalışabilir halde tutmak için geliştirilmiş disiplindir. örneğin her commit sonrası unit test, 4 saatte bir integration test, gecelik olarak functional testler bir ci server üzerinde çalıştırılır. Bu build lerden herhangi birisini bozan işini gücünü bırakır ilgili sorunu fixler, fixlemezse product owner developerı bi güzel fixler. Bu şekilde saldım çayıra mevlam kayıra metodolojisinden uzak durulur."
Kendi cümlelerimle özetlemek gerekirse, aşağıdakilerin olmasını istiyorsanız CI sistem kurmanız gerekmekte:
  • Entegrasyon problemlerini minimize etmek, 
  • Sürekli olarak build edilebilir, güncellenen, sürümlendirmesi yapılan kodlarınızı tutmak,
  • Geliştirdiğiniz yazılım ürününü sürekli çalışabilir halde tutmak,
  • Düzenli olarak birim testleri, kod gözden geçirmeleri, kodlama standartlarını, bug tespitini yapmak,
  • Projenizin gidişatını görsel olarak raporlamak, istatistik almak,
  • Tüm bu işlemler sırasında geliştiriciler arasında projenin gidişatı ile ilgili otomatik haberleşmeyi (sms, mail) sağlamak, ("Gönderdiğin kod güncellemeleri projenin şurasını bozdu, bir an önce şu şu yerleri kontrol edip düzeltilmesini sağlar mısın?" tarzında mesajlar)
  • Ekibe projenin her an ilerlediğini ve entegrasyon hatası olursa sistemin kendisini otomatik uyaracağını, kendisine işin doğrusunu yapmakta katkısı olduğunu ve tüm ekibin bu şekilde çalıştığını hissettirmek, böylece ona güven vermek,
  • Çıkaracağınız ürünü yazılım mühendisliği açısından kaliteli kılmak, dolayısı ile ürünü kaliteli kılmak,
  • ... ve belki de şu an aklıma gelmeyen bir çok fayda...
Aslında bu saydıklarım, herhangi bir entegrasyon sürecinde olması gereken adımlar. Sürekli entegrasyon deyince bu adımların tamamının bir kere ayarlanması ondan sonra sadece küçük müdahaleler ile, saat gibi tıkır tıkır her şeyin vaktinde otomatik olarak araçlar ile çalıştırılması ve seyredilmesi akla gelmelidir. Sürecin neredeyse tamamını araçlar işletir, CI yöneticisine sadece sistemdeki bir hata veya yeni bir özellik eklenmesi durumunda ihtiyaç duyulur. (Burada da aslında harcanacak vakit çok azımsanacak bir vakit değil ama ortaya çıkan iş açısından feda olsun deneceğinden eminim)
Eski yaklaşımlar yukarıdaki adımların tamamının belirli dönemlerle entegre edilmesi fikrine dayanmaktadır. Yeni yaklaşımımız ise bu sürecin her saat veya her gün sürekli tekrar edilmesi şeklindedir ki artık orta boy ve üzeri yazılım projelerinde bazı riskleri minimize etme adına bu vazgeçilemez bir hal almıştır.
Sürekli Entegrasyon Süreci
Olayın anlaşılması için bir de şekil üzerinden bakalım duruma. Yukarıda bir java web projesi tecrübesinden hareketle sürekli entegrasyon sürecini anlatan bir şekil çizmeye çalıştım. Diğer tipteki projeler içinde örnek kabul edilebilir. Görüldüğü üzere süreç geliştiriciler ile başlamakta. Geliştiricinin yapmış olduğu bir commit çelik kasa gibi görünen repoya gelmekte (Svn). Sürekli entegrasyon sunucumuz (kısaca SES diyelim, yani Jenkin aracımız) ise svn deki güncel kodları alıp, derleyip, birim testlerini yapıp, kod kalitesinden geçirip, tag leyip vs (bir çok işlem yaptırılabilir), oluşan derlenmiş projemizi web portallerine gönderir (Deploy eder). Burada bir kaç konuyu açalım. SES her commit geldiğinde de bu işi yapabilir, her gün belli saatlerde de yapabilir, bir başka projeyi çalıştırıp bitirdikten sonra otomatik tetiklenerek de yapabilir. Bu gibi daha bir çok konfigürasyon seçeneğine sahiptir. Bu takvimleme sıklığı, SES yöneticisinin tercihlerine bağlı bir durumdur. Tabii SES yöneticisi de keyfine göre değil, proje ihtiyaçlarına uygun bir konfigürasyon belirlemeye çalışacaktır. Projelerde genel kabul en azından iki ayrı sürüm çıkarmaktır.
  • Bir geliştirici sürümü çıkarılır ki bu her commit de veya 2 saatte bir gibi sıklıkla çalışan bir Jenkins job u demektir. Bu sürüm daha çok geliştirici hatasını bir an önce görsün diye çıkarılır. 
  • Bir de test sürümü çıkartılır ki bu 3 günlük veya haftalık olabilir. Bu proje ekibinin geliştirme hızına, test ekibinin büyüklüğüne vs bağlıdır.
Eğer sistemde veri tabanı kullanılıyorsa test ve geliştirici sürümleri farklı veri tabanlarına bağlı, değiştirilebilir ortak bir dosya havuzu kullanılıyorsa yine test ve geliştirici sürümleri farklı havuzları kullanmalıdır. İki sürümün ortak olabileceği örnek bir unsur, mesela Ldap otantikasyonu gibi sürümlerin birbirlerine müdahale etmeyeceği bağımsız testlerinin yapılabileceği unsurlar olmalıdır. Aksi takdirde mesela veri tabanı ortak olsa, tutulan bir değerin geliştirici sürüm tarafında silinmesi, değiştirilmesi, test sürümünü test eden test ekibini çalışamaz hale getirecektir.
Sistemde hata olduğu an SES tarafından ilgili geliştiriciye (Geçerli build'deki commit sahipleri) anında mail atılır ve patlamayla (yukarıdaki alıntılarda daha formal olsun diye kırılma olarak yazılmış) ilgili bilgi verilebilir. Neyin patlama sebebi olacağı da yine SES yöneticisine kalmıştır. Build hatası zaten varsayılan patlama sebebi sayılacaktır. Ama mesela kodların yedeğinin bir başka bilgisayara atılması bir alt iş olabilir (Scriptler ile basitçe yapılabilir) ve attığınız makineye erişim sıkıntısı veya diskin dolu olması gibi bir hatayı dahi patlama sebebi sayıp bu durumda sürümün kırıldığını kabul edebilirsiniz. Tabii bu durumda gelecek mail geliştiriciden ziyade SES yöneticisini ilgilendirecektir.

Evet CI anlamak ve biraz olsun sindirmek için bu kadar ön bilgi yeterli, gelelim temel amacımıza.
Bu yazı dizisinde, gerekli araştırmayı yapmış, "iyi ama nereden başlayacağız bu işe" diyenler için pratik bilgilerle birlikte bir yol haritası sunmaya çalışacağım, faydalı olmasını diliyorum...

İlk iş olarak, kullanacağımız araçlardan biraz bahsedelim.
1. Apache Tomcat (Jenkins aracımızı deploy etme amacıyla)
2. Jenkins (Eski adı ile Hudson ki hala farklı adlarla (Eclipse Hudson) devam ettirilmeye çalışılmakta)
3. Ant (Jenkins'te koşacak build scriptlerimiz için)
4. Sonar (Kod gözden geçirme, kod kalitesi ve çeşitli programlama metriklerin hesaplanması için)

"Her şey güzel de bu kadar yazı okuduk, araçları da gördük ama projemizde kullandığımız programlama diline dair bir şey görmedik henüz" der gibisiniz  muhtemelen :) Kullanacağımız tüm araçlar neredeyse dilden bağımsız (adını duymadığım bazı diller var, sonar aracının onlara herhangi bir plug-in i olmayabilir, onun için neredeyse diyorum) bir şekilde size sürekli entegrasyon ortamını sağlayacaklar emin olabilirsiniz. Ben Java ile sürekli entegrasyon süreci atlatmış biri olarak Java dan başlayacağım örneklerime, yeni projemde aynı işlemleri c++ için de oturtmam gerekecek, vakit olur da sıra gelirse c++ için de bu yazı dizisine devam etmeyi düşünüyorum. Baştan söyleyeyim bazı ufak tefek değişiklikler haricinde dil olayı çok fazla bir uğraş verdirmeyecektir diye düşünüyorum. Yalnız şöyle bir sonuç kaçınılmaz olacak, yukarıdaki araçlar Java-merkezli olduğundan Java projeleri için daha fazla plug-in e sahipler bunu baştan söylemek lazım. Dolayısı ile Java projelerinizde c++ projelerine göre daha çok plug-in, daha fazla esneklik, daha fazla görsellik vs. demek olacak bunu kabul etmek lazım.

Bir sonraki yazımızda Jenkins ve Hudson arasında kalanlar için "Jenkins mi Hudson mı ?" adlı bir yazı kaleme aldım, okuyabilirsiniz.