Continuous Integration (CI) Üzerine Laflamalar

Tam 4 ay 4 gündür (gün sayan taze baba modeli) bir sorunun çözüm modeli üzerine hayaller kuruyorum:

Sorun

Oğlumun acıkması

İhtiyaç Analizi

Bir miktar ısıtılmış su ve bir miktar toz mamanın bir biberon içerisinde buluşturulması ve bu karışımın uygun sıcaklık değerinde homojen bir şekilde karışması. Ayrıca “besleme” süreci belirli ve kesin bir zaman aralığında gerçekleşen bir eylem olmadığından, bekleyen ve ısısını kaybeden biberonun otomatik olarak tekrar uygun sıcaklığa getirilmesi.

Geliştirme maliyeti

0.01 baba/gün.

Geliştirme analizi

İhtiyaç analizindeki tüm eylemlerin senkron ve tekrarlı bir şekilde salt geliştirici sorumluluğunda geliştirilmesi.

Evet, gördüğünüz üzere çözüm modelim geçmişten bugüne üretilen modelden ne bir eksik ne de bir fazla. Aslında toz mama ve su her daim geliştirme ortamımda var. Diğer servislerle (MixingService, HeatingService, HeatTrackingService) entegre bir çalışma modeli geliştirebilmiş olsaydım tüm bu işlemler benim kontrolümdeki otomatize edilmiş bir süreçten geçecek ve olası bir hatada (karışımın homojen olmaması, ısının yeterli düzeyde olmaması, mama soğuduğunda farkedilememesi) uyarılmam sağlanarak hatayı çözmem ve süreci hızlıca iyileştirebilmem mümkün olacaktı.

Tabii ki bu işin latifesi, ben bu işi manuel olarak yapmaktan gayet memnunum :) Ancak profesyonel yaşantıma döndüğümde otomatize edilmiş süreçler bana fazlasıyla güven veriyor (güvenli eller tarafından oluşturulmuş). Bu otomatize etme ve otomasyonun devamlılığın sağlanması hususunda ise iki temel kavram hayatımıza giriyor: Yazının temel konusu olan “Continuous Integration (CI)” ve “Continuous Deployment (CD)”.

Genellikle bu tip yazılarda en sonda söylenen şeyi ben önce söylemeyi tercih ediyorum. CI ve CD kavramları birbiriyle “yaptıkları iş bakımından” fazlaca karıştırılıyor. Bu sebeple yazıma gündelik hayatımdan bir örnekle giriş yapmak istedim.

Continuous Integration (CI)

Yazılan kodun, geliştirilen modülün — kısaca geliştirme ortamından çıka gelen bir parçanın — projeye dahil edilmesi esnasında bir takım süreçlerden geçirilmesine verilen isim. Bağımlılıkların repolardan indirilmesi, projeye dahil edilmesi, geliştirilen kod parçacığın testlerden (unit, integration, vs…) geçirilmesi, olası durumlara göre geliştiriciye veya işin sorumlusuna bilgi verilmesi (push notification, sms, mail, vs…), işin paketlenmesi gibi eylemlerin tamamı, genellikle bu kavramın bir parçası olarak hayatımızda yer ediyor.

Continuous Deployment(CD)

CI sürecinden başarıyla geçen paketin ortamlara (en yalın haliyle Development, Test, Production) dağıtılmasından sorumlu süreç olarak karşımıza çıkmakta. Farkettiyseniz giriş örneğinde besleme eyleminden (sorunsuz paketin ortamda yayınlanması) hiç bahsetmedim :)

Bu yazının konusu da 2 kavramdan ilki; CI.

En çok kullanılan CI araçlarının logoları

CI sürecini yönetecek fazlaca araç günümüz teknolojisinde geliştiricilere sunulmuş durumda. Bunların bazıları açık kaynak kodlu, bazıları lisans gerektiriyor. Bazıları ise public repolar için ücretsiz, private repolar için lisans maliyeti gibi farklı gelir modelleri ile pazardalar. Her biri de kendine göre bazı özellikleri ile bir diğerini geçme telaşında. Tabii ki bu telaş biz geliştiriciler için bulunmaz nimet :)

Bizler Hürriyet’te, TeamCity aracını kullanıyoruz. Jetbrains ürünü ve agent başına lisanslama yöntemi ile çalışıyor. Oldukça güçlü ve kullanım kolaylığı sağlayan bir arayüzü var. Ancak on-premise çalışıyor. Teamcity ile çalışmak isterseniz kendinize ait bir sunucu üzerinde konfigüre etmeli ve yönetmelisiniz.

Benim kişisel olarak favorim Travis CI. Nedenlerini sıralamak gerekirse;

  • Public repository’ler için tamamen ücretsiz. travis-ci.org adresini travis-ci.com olarak değiştirip giriş yaparsanız bu sefer de private repository’leriniz için kullanabileceğiniz ve lisans temin edebileceğiniz “kurumsal” siteye yönlenebilirsiniz.
  • Herhangi ekstra bir üyeliğe ihtiyaç duymuyor. Github hesabınızla giriş yapıp, repolarınızı araç ile senkron edebilirsiniz.
  • Teamcity, Bamboo gibi araçların güçlü arayüzleri aksine “integration as code” kavramı benim daha çok ilgimi çekiyor. Bash, powershell gibi güçlü komut satırı uygulamaları ile betikler yazmak ve bu betiklerle süreci yönetmek daha kontrollü bir hissiyat yaratıyor.
  • Projenize bir bağımlılık eklemek zorunda değilsiniz. yml uzantılı bir dosya üzerinden tüm CI sürecinizi kodlayabilirsiniz.
  • Detaylı bir şekilde CI sürecinizi logluyor ve hata/başarı durumunda sizi bilgilendiriyor.
  • Diğer servislerle (Docker, AWS, Azure, Google, Slack, vs…) olan entegrasyonlarınız için “Key-Value” değerlerinizi saklayabileceğiniz bir konfigürasyon ekranı da size sunuyor.

Bunun gibi onlarca maddeyi alt alta sıralayabiliriz tabii ki (bu konuda tecrübeli arkadaşlar yorum üzerinden ekleme yaparlarsa mutlu olurum).

Bu noktada favorilerime bir yenisini daha ekledim. Yakın zamanda twitter feed’ime düşen bir ürün: Shippable.

Shippable — Yeni Nesil CI Aracı

Travis’in sunduğu (benim kullandığım kadarı ile) tüm özellikleri sunmakla birlikte en çok hoşuma giden kısmı Junit test raporlarını ve test coverage raporlarını ayrıca sunan ekran. https://github.com/selcukusta/netcore-ci-tools adresinde her iki araç için de oluşturduğum konfigürasyon dosyaları mevcut. Bu proje içerisinde bir de test projesi mevcut ve aşağıdaki gibi bir test sınıfı var:

Bu testleri CI sürecime dahil ettim ve Shippable bana şu şekilde bir bilgi döndü:

Yine Shippable’ın en güzel ve güçlü özelliği bir takım servislerle direkt entegrasyon sağlayabilmesi. Aşağıda bazı servislerin listesi mevcut:

Repo adresini verdiğim projemdeki shippable.yml dosyasını anlatmak gerekirse;

Bu CI sürecinde microsoft/dot-net:1.1-sdk image’ı kullanılacak. “xsltproc” adlı linux paketini indir, bir takım klasörlere yazma izni ver, bir takım script dosyalarını çalıştır ve CI süreci tamamlandıktan sonra çıkan paketi docker’a push et.

Burada dikkat çekici nokta Docker için herhangi bir kullanıcı adı ve şifre belirtilmemesi. İşte otomatik servis entegrasyonları burada devreye giriyor. yml dosyasının sonundaki “integrations” alanı ile bu CI sürecinde kullanılacak olan entegrasyonları tanımlıyorum. Docker entegrasyonu için panel ise aşağıdaki gibi:

Shippable’ın son yaptığı build sonrası çıkan ve Docker’a push edilen paket ise şu adreste: https://hub.docker.com/r/selcukusta/netcore-shippable-ci-test-sample/

Bir sonraki yazıda tekrar görüşene dek, entegrasyonlarınız sıkıntısız olsun :)