CI/CD Pipeline Nedir? Kod Yazmaktan Production'a Giden Otomatik Yol
Bir özellik geliştirdiniz. Çalışıyor. Şimdi ne yapıyorsunuz?
Test ediyorsunuz, build alıyorsunuz, sunucuya yüklüyorsunuz, servisi yeniden başlatıyorsunuz. Her seferinde. Her değişiklik için. El ile.
Bu sadece zaman kaybı değil — her manuel adım bir hata potansiyeli. Yanlış branch'i deploy etmek, testi atlamak, eski build'i yüklemek. CI/CD pipeline bu sürecin tamamını otomatikleştirir ve insan hatasını denklemden çıkarır.
CI ve CD: İki Ayrı Kavram
CI (Continuous Integration — Sürekli Entegrasyon): Geliştiricilerin kod değişikliklerini sık sık (günde birden fazla kez) ortak bir branch'e entegre etmesi ve her entegrasyonda otomatik testlerin çalışması. Amaç: hataları erken yakalamak, entegrasyon sorunlarını biriktirmemek.
CD (Continuous Delivery / Continuous Deployment):
Continuous Delivery — kod her zaman deploy edilebilir durumda tutulur. Production'a almak manuel bir onay gerektirir ama teknik olarak her an hazır.
Continuous Deployment — her başarılı CI çalışması otomatik olarak production'a deploy edilir. Hiçbir insan müdahalesi olmadan.
Geliştirici → Git Push → CI Tetiklenir → Testler Çalışır → Build Alınır
↓
CD: Staging'e Deploy → Onay → Production
Pipeline'ın Anatomisi
Bir CI/CD pipeline tipik olarak şu aşamalardan oluşur:
1. Trigger: Bir event pipeline'ı başlatır. main branch'e push, pull request açılması, tag oluşturulması.
2. Build: Kod derlenir (gerekiyorsa), bağımlılıklar yüklenir, artifact oluşturulur.
3. Test: Unit testler, integration testler, linting, code coverage kontrolü.
4. Security Scan: Bağımlılıklardaki güvenlik açıkları, container image taraması.
5. Deploy to Staging: Test ortamına otomatik deploy.
6. Smoke Tests: Production'a benzer ortamda temel akışların çalıştığını doğrulama.
7. Deploy to Production: Manuel onay veya otomatik.
GitHub Actions ile Pratik Pipeline
GitHub Actions, GitHub'a entegre CI/CD platformudur. Repository'nize .github/workflows/ klasörü altında YAML dosyası ekleyerek pipeline tanımlarsınız.
# .github/workflows/ci.yml name: CI/CD Pipeline on: push: branches: [main, develop] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" - name: Install dependencies run: npm ci - name: Run linter run: npm run lint - name: Run tests run: npm test -- --coverage - name: Upload coverage report uses: codecov/codecov-action@v3 build: needs: test # test gecmeden build baslamaz runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t myapp:${{ github.sha }} . - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Push Docker image run: docker push myapp:${{ github.sha }} deploy-staging: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/develop' steps: - name: Deploy to staging run: | ssh deploy@staging.example.com \ "docker pull myapp:${{ github.sha }} && \ docker stop myapp || true && \ docker run -d --name myapp -p 3000:3000 myapp:${{ github.sha }}" deploy-production: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' environment: production # Manuel onay gerektirir steps: - name: Deploy to production run: | ssh deploy@production.example.com \ "docker pull myapp:${{ github.sha }} && \ docker stop myapp || true && \ docker run -d --name myapp -p 3000:3000 myapp:${{ github.sha }}"
needs keyword'ü bağımlılık zinciri kurar — test geçmeden build, build geçmeden deploy çalışmaz.
environment: production ile GitHub'da manuel onay adımı eklenebilir. Birisi "Approve" demeden production deploy başlamaz.
Secrets Yönetimi
Pipeline'da şifre, API key, token gibi hassas bilgiler hiçbir zaman YAML dosyasına yazılmaz. GitHub Secrets veya benzeri bir vault sistemiyle yönetilir.
# Doğru: Secret'tan oku - name: Deploy env: DATABASE_URL: ${{ secrets.DATABASE_URL }} API_KEY: ${{ secrets.API_KEY }} run: ./deploy.sh # YANLIS: Asla böyle yapma - name: Deploy run: DATABASE_URL=postgres://user:password@host/db ./deploy.sh
Secret'lar GitHub repository Settings > Secrets altında tanımlanır. Log'larda otomatik olarak *** ile maskelenir.
Branch Stratejisi ve Pipeline
Pipeline tasarımı branch stratejinizle uyumlu olmalı:
Feature branch'ler: Her push'ta lint + unit test çalışır. Hızlı feedback, hafif pipeline.
develop branch: Full test suite + integration testler + staging deploy.
main branch: Full test suite + security scan + production deploy (onaylı).
Pull Request: Test çalıştır, coverage kontrolü yap, review zorunlu tut.
on: push: branches: [main, develop] pull_request: branches: [main, develop]
Deployment Stratejileri
Rolling Deployment: Yeni versiyon instance'ları tek tek güncellenir. Downtime yok ama bir süre eski ve yeni versiyon aynı anda çalışır.
Blue/Green Deployment: İki özdeş ortam var (blue = aktif, green = yeni versiyon). Yeni versiyon green'e deploy edilir, test edilir, traffic bir anda green'e yönlendirilir. Sorun olursa blue'ya anında dönülür.
Canary Deployment: Yeni versiyon önce trafiğin küçük bir yüzdesine (örneğin %5) gönderilir. Metrikler izlenir, sorun yoksa yüzde artırılır.
Blue/Green:
Traffic → Blue (v1) Traffic → Green (v2)
Green (v2) hazır → Blue (v1) standby
Neden Pipeline Olmadan Çalışmak Tehlikeli
"Küçük projede gerek yok" denilen pipeline'lar, proje büyüdükçe en çok acı veren borçlardan biri haline gelir.
Test yazmak zorunlu hale gelmez, çünkü kimse çalıştırmıyor. Deploy korkusu artar, release sıklığı azalır. "Çalışıyor, dokunma" kültürü yerleşir. Bir hata production'a çıktığında kimin neyini deploy ettiği belli olmaz.
CI/CD pipeline küçük projede kurulması en kolayken kurulur. Büyük projede kurulması en zor, en maliyetli ve en çok dirençle karşılaşılan dönemde kurulmak zorunda kalınır.
Kod commit edildiği andan production'a ulaşana kadar geçen süreyi ve bu süredeki insan müdahalesini minimuma indiren her şey, yazılım geliştirmeyi daha güvenli, daha hızlı ve daha öngörülür hale getirir.