Jenkins Pipeline ile Proje Deployment

Kısa bir ara verdikten sonra Jenkins yazılarımıza devam ediyoruz. Daha önceki yazılarımızda Debian üzerine kurulum ve Freestyle Project hakkında genel bilgi vermeyi hedefledik. İlgili konulara hızlıca göz atmak için aşağıdaki makaleleri inceleyebilirsiniz.

Sıradaki konumuz ise bir örnek üzerinde bir projenin nasıl otomatize edilerek build edilebileceği. Örneğimiz üzerinde bir ReactJS projesinin build edilip basit bir şekilde ayağa kaldırılmasını inceleyeceğiz. Örnekte uygulanan metotlar sizin projenizle uyuşmayabilir ancak fikir vermesi ve uygulanış biçiminin akılda kalması açısından faydalı olacağı kanısındayım.

Ufaktan başlayacak olursak; projemiz ReactJS’in kurulum sonrası gelen varsayılan ekranı olacak. Bizim bu projeyle yapmak istediğimiz ise GitHub üzerinde proje için herhangi bir “push” işlevi gerçekleştiğinde -master branch özelinde- bu değişikliklerin haberini GitHub WebHooks ile Jenkins’e iletmek ve üzerinde projemizi build edip Docker üzerinde ayağa kaldırmak olacak.

Bu işlemlerimizden sunucu üzerinde yapılması gereken “bir ReactJS projesinin deployment“ı için yapılması gerekenleri, farklı yollar da var ancak konumuz bu değil, ise Jenkinsfile üzerinden yapacağız. Konu sırasının dağılmaması açısından birkaç satır sonrasına Dockerfile oluştururken tekrar değineceğiz.

Yapının ufak tanıtımı sonrası yapılacaklar listemiz ise kısaca şöyle:

  • Jenkins üzerinde bir pipeline projesi oluşturmak,
  • GitHub üzerinden GitHub WebHook bağlantısı yapmak,
  • Projemiz üzerinde Jenkinsfile olacak şekilde değişikler yaparak GitHub üzerine push’lamak.

Sırasıyla başlıklarımıza geçelim.

Jenkins üzerinde bir pipeline projesi oluşturmak

Bir pipeline projesi oluşturmak için Freestyle Project’te yaptığımız gibi giriş yaptıktan sonra sol menüden “New Item” ve ardından isim vererek “Multibranch Pipeline” seçeneğini seçiyoruz. Görsellerle destekleyecek olursak sırasıyla aşağıdaki şekildedir:

jenkins create pipeline

“?”

Neden “Pipeline” değil de “Multibranch Pipeline” seçtiğimizin kısaca cevabı Jenkinsfile’ı default olarak kullanabilmek. Ek olarak projenizin ileride/şuan birden fazla branch içerebileceğini ve bu branch’leri ayrı birer Jenkinsfile ile kontrol edebileceğimiz için bizim için şuan daha avantajlı.

Sonrasında pipeline yapılandırması ekranında “General“, “Branch Sources” ve “Build Configuration” kısımlarına cevap vermemiz bu proje için yeterlidir. Projeniz GitHub üzerinde gizli ise gerekli credentials değerlerini verip doğruladığınızdan(validate) emin olun.

Branch Sources kısmında GitHub seçerek ilgili repo’nun adresini ve gerekli bilgileri girdikten sonra altında bulunan bir alt başlık olan “Behaviour” kısmında Jenkins’in hangi durumlarda aktif olacağını değiştirmek size kalmış. Bu örnek için biz varsayılan değerleri kullanacağız.

Build Configuration kısmında ise projemizin pipeline’ının Jenkinsfile üzerinden okuyarak ona göre yapacağını belirtiyoruz.

jenkins pipeline config

Bu kısımda yapacaklarımız bu kadardı. Pipeline item’ini kaydettiğimizde ilk build için çalışıyor olduğunu görebilirsiniz.

GitHub üzerinden GitHub WebHooks bağlantısı yapmak

WebHooks özetle repo içerisindeki herhangi bir aktivitenin bir adrese haber verilmesi olarak düşünülebilir. Projemizde giriş için bir seferlik build etmiş olsa bile her PR sonrası Jenkins’e girip build etmesi için komut vermek zahmet artıran bir durum. Bizi bu dertten kurtaran WebHooks için GitHub üzerinde proje repo’suna girip Setting altına açılan sol menüden WebHooks’a girip yeni bir webhook oluşturmamız gerekecek.

settings webhook

Açılan form sayfasında Payload URL ve Content Type kısımlarını dolduruyoruz. Altta bulunan alanlarda ise hangi durumlarda ileteceğimizi belirliyoruz.

Payload URL:

Eğer Jenkins üzerinde GitHub WekHooks URL değişikliği yapılmadıysa varsayılan değer olan Jenkins_URL/github-webhook/ adresini giriyoruz.

webhook config

Burada karşılaşabileceğiniz muhtemel iki sorun ve çözümleri ele alalım:

İlk olarak evde kenarda duran sunucunuz dışarıya açık değilse ve GitHub ile haberleşmesini sağlayamıyorsanız bu durumun üstesinden gelmek için ngrok kullanılabilir.

İkincisi ise, Jenkins içinde GitHub plugin’lerinin sizde var olduğunu varsayarsak, Payload URL kısmından emin olamamanız veya değiştirmek istemeniz. Bu durumda ise Jenkins anasayfası üzerinden sırasıyla Manage Jenkins -> Configure System -> GitHub -> Advanced tıklamalarını yaparak “Override Hook URL” ile istediğiniz adresi kullanabilirsiniz.

WebHook yapılandırmamıza geri dönecek olursak; burada bulunan Secret’ı şuan için boş geçiyoruz ancak Secret değişkenini, verdiğimiz adrese yapılan isteklerin GitHub üzerinden geldiğini doğrulamak için de kullanabilirsiniz.

Son olarak webhook’umuzu ekledikten sonra kontrol edecek olursak webhook’umuzun görseldeki gibi işaretlenmiş olması iyiye işaret.

webhook result

Burada bir hata almanız durumunda “Edit” diyerek en altta bulunan Recent Deliveries kısmından detaylı olarak hata kodu v.s. görme imkânınız var. Bu çıktılara göre hatalarınızı analiz edip daha kolay çözüm üretmeniz mümkün olacaktır.

webhook control

GitHub üzerindeki yapılandırmalarımız şuan için bu kadar.

Projemiz üzerinde Jenkinsfile olacak şekilde değişikler yaparak GitHub üzerine push’lamak

Bu kısım, daha çok bir şeyler yazacağınız yer. Proje dosyalarımız içerisinde bulunan Jenkinsfile ile, daha önce de bahsettiğimiz gibi, proje değişiklerinden sonra build esnasında neler yapılacağını yazacağız. Bir bakıma yemek tarifi yapar gibi build esnasında neler yapıyorsak buraya geçiriyoruz.

Şuan için Jenkinsfile‘nin bir build tarifi olduğunu söylerek nasıl yazılır v.s. gibi konulara girmiyoruz.

node {
  try {
    stage('Checkout') {
      checkout scm
    }
    stage('Environment') {
      sh 'git --version'
      echo "Branch: ${env.BRANCH_NAME}"
      sh 'docker -v'
      sh 'printenv'
    }
    stage('Deploy'){
      if(env.BRANCH_NAME == 'master'){
        sh 'docker build -t react-app --no-cache .'
        sh 'docker tag react-app localhost:5000/app'
        sh 'docker run -p 5002:3000 -d localhost:5000/app'
      }
    }
  }
  catch (err) {
    throw err
  }
}

Burada kısaca kontrol evresini geçip projenin içerisindeki Dockerfile’den yararlanarak projemizi build edip 5002 portundan sunulmasını istiyoruz. Dockerfile ise aşağıdaki gibidir:

# Extending image
FROM node:carbon

RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get -y install autoconf automake libtool nasm make pkg-config git apt-utils

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Versions
RUN npm -v
RUN node -v

# Install app dependencies
COPY package.json /usr/src/app/
COPY package-lock.json /usr/src/app/

RUN npm install

# Bundle app source
COPY . /usr/src/app

# Port to listener
EXPOSE 3000

# Serve
RUN npm install -g serve

# Environment variables
ENV NODE_ENV production
ENV PORT 3000
ENV PUBLIC_PATH "/"

RUN npm run build

# Main command
CMD [ "serve", "-s", "build", "-l", "3000"]

Böylece projemizi yayına almış oluyoruz ancak burada fark edeceksinizdir ki bir sonraki PR bir docker image’i daha çalıştıracağı ve aynı portta bir önceki çalışıyor olacağı için öncesinde eski build’i yayından kaldırmak için Jenkinsfile’de değişiklikler yapılabilir. Bu bakımdan bu örnek dosyalar uygulamanız için yeterli olmayacaktır. Burada genel kullanım anlatıldığı için bunları göz ardı ediyoruz.

Sonuç olarak

Tüm bu işlemlerin sonunda localhost’umuzda bizi bekleyen bir ReactJS uygulamamız oldu. Aynı mantıkla böyle bir aracı kullanarak uygulamanızı çeşitli evrelere bölebilir, farklı şekillerde ve farklı yerlerde build edip canlıya alabilir, çeşitli testlerden veri elde etmek için kullanabilir ve daha nice uygulamalarda araç olarak alet çantanızda bulundurabilirsiniz.

ReactJS app result

Kaynakça:

Leave a comment