GitLab CI/CD Pipeline Oluşturma Rehberi
Modern yazılım geliştirme süreçlerinde hız, güvenilirlik ve otomasyon vazgeçilmez unsurlardır. Sürekli Entegrasyon (CI) ve Sürekli Dağıtım (CD) pratikleri, bu hedeflere ulaşmak için kritik öneme sahiptir. GitLab, entegre bir SCM (Source Code Management) ve CI/CD platformu olarak geliştiricilere projelerini uçtan uca yönetme imkanı sunar.
Bu rehberde, GitLab CI/CD’nin temel prensiplerini, pipeline yapısını ve projenizde nasıl etkili bir şekilde kullanabileceğinizi adım adım inceleyeceğiz. Amaç, kodunuzu otomatik olarak test eden, derleyen ve dağıtan sağlam bir pipeline oluşturmaktır.
GitLab CI/CD Nedir ve Neden Kullanmalıyız?
Sürekli Entegrasyon (CI): Geliştiricilerin kod değişikliklerini ana depoya sık sık entegre etme pratiğidir. Her entegrasyon, otomatik testler ile doğrulanır, böylece hatalar erken aşamada tespit edilir.
Sürekli Dağıtım (CD): CI aşamasını geçen kodun, otomatik olarak üretim ortamına veya bir ara ortama dağıtılmasıdır. Sürekli Dağıtım, genellikle Sürekli Teslimat’ı (Continuous Delivery) da kapsar, ki bu da kodun her an dağıtıma hazır olduğu anlamına gelir.
GitLab CI/CD kullanmanın başlıca faydaları:
- Otomasyon: Manuel hataları azaltır, tekrarlayan görevleri otomatikleştirir.
- Hız: Kod değişikliklerini daha hızlı entegre eder ve dağıtır, pazar süresini kısaltır.
- Güvenilirlik: Her değişiklik otomatik testlerden geçtiği için hatalar erken yakalanır, üretimdeki sorunlar minimize edilir.
- Tutarlılık: Dağıtım süreçleri her zaman aynı şekilde işler, ortamlar arası farklılıklar azalır.
- Görünürlük: Pipeline durumu herkes tarafından izlenebilir, geliştirme ve operasyon ekipleri arasında şeffaflık sağlanır.
.gitlab-ci.yml Dosyası: Pipeline’ınızın Kalbi
GitLab CI/CD pipeline’ınızın tüm tanımlamaları, projenizin kök dizininde bulunan .gitlab-ci.yml adlı bir YAML dosyasında yapılır. Bu dosya, GitLab Runner tarafından okunur ve pipeline’ın nasıl çalışacağını belirler.
Bir .gitlab-ci.yml dosyası genellikle şunları içerir:
stages: Pipeline’daki mantıksal aşamaların sırası.jobs: Her aşamada çalışacak bağımsız görevler.scripts: Her job içinde çalıştırılacak komutlar.image: Job’ların çalışacağı Docker imajı.cache,artifacts,variables: Performans ve veri yönetimi için yardımcı anahtarlar.
Temel Yapı Taşları
1. Stages (Aşamalar)
Pipeline’ınızın akışını tanımlayan mantıksal gruplardır. Job’lar, tanımlanan aşamalar içinde çalışır ve bir aşamadaki tüm job’lar başarılı olmadan bir sonraki aşama başlamaz (varsayılan davranış).
stages:
- build # Uygulamayı derle
- test # Testleri çalıştır
- deploy # Uygulamayı dağıt
Bu örnekte, önce build aşamasındaki tüm job’lar, ardından test aşamasındaki job’lar ve son olarak deploy aşamasındaki job’lar çalışacaktır.
2. Jobs (Görevler)
Pipeline’ınızın çalıştırdığı en küçük bağımsız birimlerdir. Her job, belirli bir stage‘e atanır ve bir dizi script komutu çalıştırır. Job’lar varsayılan olarak aynı aşamadaki diğer job’larla paralel olarak çalışır.
build_frontend_job:
stage: build
script:
- echo "Frontend uygulaması derleniyor..."
- npm install
- npm run build
run_unit_tests:
stage: test
script:
- echo "Birim testleri çalıştırılıyor..."
- npm test -- --coverage
3. Script (Komutlar)
Her job içinde çalıştırılacak Shell komutlarıdır. Birden fazla komut alt alta yazılabilir. Her komut ayrı bir satırda yazılmalıdır.
deploy_production:
stage: deploy
script:
- echo "Üretim ortamına dağıtım başlatılıyor..."
- scp -r build/* user@your-production-server:/var/www/html/app/
- ssh user@your-production-server "systemctl restart nginx"
- echo "Dağıtım tamamlandı."
4. Image (Docker İmajı)
Her job’ın çalışacağı ortamı belirleyen Docker imajıdır. Bu, farklı projeler için izole ve tutarlı ortamlar sağlamanın harika bir yoludur. Job seviyesinde veya global olarak tanımlanabilir.
build_job:
image: node:18-alpine # Node.js 18 ve Alpine Linux tabanlı bir imaj
stage: build
script:
- npm install
- npm run build
Global bir imaj tanımlayarak tüm job’ların aynı imajı kullanmasını sağlayabilirsiniz:
image: python:3.10-slim
stages:
- lint
- test
lint_code:
stage: lint
script:
- pip install flake8
- flake8 .
run_pytest:
stage: test
script:
- pip install pytest
- pytest
Yardımcı Anahtarlar ve Optimize Edici Ayarlar
1. Variables (Değişkenler)
Pipeline’ınızda yeniden kullanılabilir değerler tanımlamanızı sağlar. Proje ayarları veya hassas bilgiler (CI/CD ayarlarında maskelenebilir/korunabilir) için kullanışlıdır. GitLab’ın ön tanımlı değişkenleri (CI_COMMIT_BRANCH, CI_PROJECT_DIR vb.) de mevcuttur.
variables:
FRONTEND_APP_PATH: frontend/my-app
BUILD_OUTPUT_DIR: build
build_frontend:
stage: build
script:
- cd $FRONTEND_APP_PATH
- npm install
- npm run build
- mv $BUILD_OUTPUT_DIR ../../
2. Cache (Önbellek)
Job’lar arasında veya farklı pipeline çalıştırmaları arasında bağımlılıkları (örneğin node_modules veya pip_cache) önbelleğe almanızı sağlar. Bu, pipeline’ın daha hızlı çalışmasını ve tekrar eden indirme işlemlerini engeller.
cache:
paths:
- node_modules/ # node_modules klasörünü önbelleğe alır
key: ${CI_COMMIT_REF_SLUG} # Branch'e özgü önbellek anahtarı
build_job:
stage: build
script:
- npm install
- npm run build
3. Artifacts (Ürünler)
Bir job’ın çıktısını (derlenmiş dosyalar, test raporları, log dosyaları vb.) sonraki job’lar veya indirme için saklamanızı sağlar. Genellikle expire_in ile ömrü belirlenir.
build_app:
stage: build
script:
- make build
artifacts:
paths:
- dist/ # dist klasörünü artifact olarak sakla
- app.log
expire_in: 1 day # Artifact'ler 1 gün sonra otomatik silinecek
deploy_to_server:
stage: deploy
script:
- echo "Artifact'ler kullanılarak dağıtım yapılıyor..."
- cp -r dist/* /var/www/app/ # Önceki job'dan gelen dist klasörünü kullan
4. only / except / rules
Job’ların hangi durumlarda çalışacağını kontrol etmenizi sağlar. Dallara (branches), etiketlere (tags) veya dosya değişikliklerine göre filtreleme yapabilirsiniz. rules, only/except‘e göre daha esnek ve güçlü bir alternatiftir ve karmaşık koşulları ifade etmek için kullanılır.
# only/except örnekleri
deploy_production_legacy:
stage: deploy
script:
- echo "Eski yöntemle prod'a dağıtım..."
only:
- main # Sadece 'main' dalında çalış
when: manual # Manuel olarak çalıştırılır
deploy_feature_branch:
stage: deploy
script:
- echo "Özellik dalına dağıtım..."
except:
- main # 'main' dalı hariç tüm dallarda çalışır
# rules ile daha gelişmiş koşullar
build_develop:
stage: build
script:
- echo "Geliştirme dalı için derleme..."
rules:
- if: $CI_COMMIT_BRANCH == "develop" # Eğer dal 'develop' ise
when: always # Her zaman çalıştır
- if: $CI_PIPELINE_SOURCE == "merge_request_event" # Eğer MR tetiklediyse
when: manual # Manuel çalıştır
allow_failure: true # Başarısız olursa pipeline'ı durdurma
deploy_to_production:
stage: deploy
script:
- echo "Üretim ortamına güvenli dağıtım..."
rules:
- if: $CI_COMMIT_BRANCH == "main" && $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/ # Eğer 'main' dalı ve bir sürüm etiketi varsa
when: manual # Manuel olarak çalıştır
allow_failure: false
Örnek Bir CI/CD Pipeline: Basit Bir Web Uygulaması
Şimdi, basit bir Node.js tabanlı web uygulamasını derleyen, test eden ve iki farklı ortama (staging ve production) dağıtan tam bir .gitlab-ci.yml örneği oluşturalım.
image: node:18-alpine # Tüm job'lar için Node.js 18 imajı
variables:
# Uygulamanın olduğu dizin
APP_SOURCE_DIR: ./frontend-app
stages:
- build
- test
- deploy
# Uygulamayı derleme job'ı
build_frontend:
stage: build
script:
- echo "Frontend uygulaması derleniyor..."
- cd $APP_SOURCE_DIR
- npm install # Bağımlılıkları yükle
- npm run build # Uygulamayı derle
artifacts:
paths:
- $APP_SOURCE_DIR/build/ # Derlenmiş dosyaları sonraki aşamalar için sakla
expire_in: 1 hour # Artifact'ler 1 saat sonra silinsin
cache:
paths:
- $APP_SOURCE_DIR/node_modules/ # node_modules'i önbelleğe al
# Uygulama test job'ı
test_frontend:
stage: test
script:
- echo "Frontend testleri çalıştırılıyor..."
- cd $APP_SOURCE_DIR
- npm test # Testleri çalıştır
allow_failure: false # Testler başarısız olursa pipeline durur
cache:
paths:
- $APP_SOURCE_DIR/node_modules/
policy: pull # Sadece önbelleği çek, güncelleme
# Staging ortamına dağıtım job'ı
deploy_to_staging:
stage: deploy
script:
- echo "Staging ortamına dağıtım yapılıyor..."
# Burada SSH veya başka bir dağıtım aracı ile staging sunucusuna kopyalama komutları olabilir
- ls -la $APP_SOURCE_DIR/build/ # Örnek olarak artifact içeriğini listele
- echo "Dağıtım başarılı: Staging Ortamı."
environment:
name: staging
url: https://staging.my-app.com # GitLab UI'da link olarak görünür
rules:
- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop" # main veya develop dalında otomatik çalış
when: on_success # Önceki aşamalar başarılı ise
- if: $CI_PIPELINE_SOURCE == "merge_request_event" # Merge Request'lerde de çalışabilir
when: on_success
# Production ortamına manuel dağıtım job'ı
deploy_to_production:
stage: deploy
script:
- echo "Üretim ortamına dağıtım yapılıyor..."
# Gerçek bir senaryoda bu adımda daha gelişmiş dağıtım stratejileri (Kubernetes, Blue/Green, Canary) kullanılır.
- echo "Üretim dağıtımı tamamlandı."
environment:
name: production
url: https://my-app.com
rules:
- if: $CI_COMMIT_BRANCH == "main" # Sadece main dalında
when: manual # Kullanıcı tarafından manuel olarak tetiklenmeli
allow_failure: false # Başarısız olursa pipeline durur
Bu örnekte:
build_frontendjob’ı uygulamayı derler, bağımlılıkları önbelleğe alır ve derlenmiş çıktıları (build/klasörü) artifact olarak depolar.test_frontendjob’ı testleri çalıştırır. Testler başarısız olursa, pipeline durur.deploy_to_stagingjob’ımainveyadevelopdallarına yapılan her push’ta otomatik olarak staging ortamına dağıtım yapar.deploy_to_productionjob’ı sadecemaindalında ve kullanıcı tarafından manuel olarak tetiklendiğinde çalışır. Bu, üretim dağıtımları üzerinde daha fazla kontrol sağlar.
En İyi Uygulamalar (Best Practices)
- Küçük ve Odaklı Job’lar: Her job tek bir sorumluluğa sahip olmalı (derleme, test, statik analiz, dağıtım). Bu, pipeline’ı daha anlaşılır ve yönetilebilir kılar.
- İmajları Kullanın: Tutarlı ve izole ortamlar sağlamak için Docker imajları kullanın. Gerekirse projenize özel Docker imajları oluşturun.
- Önbellekleme ve Artifact’ler: Pipeline hızını artırmak için bağımlılıkları önbelleğe alın (
node_modules,vendor,.m2vb.) ve job çıktılarını (derlenmiş kod, raporlar) artifact olarak saklayın. - Değişkenleri Kullanın: Tekrarlayan değerler, yapılandırma ayarları ve hassas bilgiler için değişkenler tanımlayın. Hassas bilgileri GitLab CI/CD ayarlarında korumalı ve maskelenmiş değişkenlerde saklayın.
- Testleri Ciddiye Alın: Test aşaması başarısız olursa pipeline’ın durmasını sağlayın (
allow_failure: falsevarsayılandır). Bu, hatalı kodun ileri gitmesini engeller. - Gelişmiş Koşullar için
rules: Job’ları koşullu olarak çalıştırmak içinonly/exceptyerine daha güçlü ve esnek olanrulesanahtarını kullanın. - Ortamları Tanımlayın: Dağıtım job’ları için
environmentanahtarını kullanarak dağıtım ortamlarını izleyin. Bu, geçmiş dağıtımları ve ortam durumunu takip etmenize yardımcı olur. - Pipeline Görselleştirmesini Kullanın: GitLab UI’daki pipeline görselleştirmesini akışı anlamak, bağımlılıkları görmek ve hataları gidermek için aktif olarak kullanın.
- Linting ve Validasyon:
.gitlab-ci.ymldosyanızı düzenlerken GitLab’ın dahili CI linter aracını kullanarak sözdizimi hatalarını kontrol edin.
Sonuç
GitLab CI/CD, yazılım geliştirme süreçlerinizi otomatikleştirmenize, hızlandırmanıza ve güvenilirliğini artırmanıza olanak tanıyan güçlü bir araçtır. .gitlab-ci.yml dosyasını doğru bir şekilde yapılandırarak, projeniz için özel ihtiyaçlara uygun, esnek ve verimli pipeline’lar oluşturabilirsiniz.
Bu rehber, GitLab CI/CD yolculuğunuzda size bir başlangıç noktası sunmayı amaçlamaktadır. Denemeler yapmaktan, GitLab dokümantasyonunu keşfetmekten ve geniş GitLab topluluğundan yardım almaktan çekinmeyin. Otomatikleşmiş ve sorunsuz bir dağıtım süreci dileğiyle!
