CI/CD Pipeline: GitHub Actions ile otomatik dağıtım

Sürekli entegrasyon ve sürekli dağıtım (CI/CD) nedir? GitHub Actions ile otomatik test, build ve deploy süreçleri.

2026-03-1015 dk okuma
CI/CD Pipeline: GitHub Actions ile otomatik dağıtım

Bir proje deposuna kod gönderdiğinizde testlerin otomatik çalışması, uygulamanın paketlenmesi ve doğru ortama tek bir hata bile yapılmadan dağıtılması... Bu, modern yazılım geliştirmenin standardı haline geldi ve GitHub Actions, bu standardı kurmanın en erişilebilir yollarından biri. Ayrı bir CI/CD sunucusu kurmaya, ek lisans ücretleri ödemeye gerek kalmadan, doğrudan kod deponuzun içinde tam teşekküllü bir pipeline çalıştırabilirsiniz.

Bu yazı, teknik uygulayıcılar için baştan sona uygulamalı bir kurulum kılavuzudur. Sıfırdan başlayıp, otomatik test, build, Docker imajı üretimi ve sunucuya dağıtım adımlarını sırayla kuracağız; her adımda kopyalanıp uyarlanabilecek workflow örnekleri vereceğiz. CI/CD'nin neden gerekli olduğunu, iş değerini ve stratejisini merak ediyorsanız bunu ayrı bir yazıda ele aldık; burada doğrudan klavyenin başına geçiyoruz. Örnekler ağırlıklı olarak bir Node.js uygulaması üzerinden ilerleyecek, ancak mantık her teknoloji yığını için aynıdır.

Not: GitHub Actions ifade söz dizimi normalde dolar işareti ve ardından çift süslü parantez ile yazılır. Bu yazıdaki örneklerde, okunabilirliği korumak için bu ifadeleri çift köşeli parantez yani [[ ... ]] biçiminde gösteriyoruz. Kendi projenizde bunları gerçek GitHub ifade söz dizimine çevirmeniz yeterlidir.

Başlamadan önce: Ön koşullar ve hazırlık

Kuruluma geçmeden önce elinizde olması gerekenleri netleştirelim. GitHub Actions, GitHub üzerinde barındırılan depolarda doğrudan çalışır; ayrı bir kurulum gerektirmez. İhtiyacınız olan şeyler oldukça basittir.

Öncelikle GitHub'da bir kod deposu ve üzerinde yönetici yetkiniz olmalı. Projenizin testleri çalıştırılabilir durumda olmalı; çünkü test edilemeyen kodun otomasyonu pek anlam taşımaz. Eğer dağıtım da yapacaksanız, hedef sunucuya ya da bulut sağlayıcısına erişim bilgilerine ihtiyacınız olacak. Son olarak, depo ayarlarındaki "Secrets and variables" bölümüne erişiminizin olması gerekir; gizli bilgileri buradan güvenle saklayacağız.

GitHub Actions, çalışmalarını belirli bir dizinde arar. Tüm workflow dosyaları, projenizin kök dizinindeki .github/workflows klasörüne YAML formatında yerleştirilir. Bu klasördeki her .yml dosyası ayrı bir iş akışı tanımlar ve GitHub bunları otomatik olarak tanır.

Geliştiricinin CI/CD pipeline kodunu yazdığı ekran görünümü

GitHub Actions nasıl çalışır? Temel yapı taşları

Pipeline yazmaya başlamadan önce, GitHub Actions'ın terminolojisini oturtmak gerekir. Sistem birkaç temel kavram üzerine kuruludur ve bu kavramları anlamak, ileride yazacağınız her workflow'u çok daha net kılar.

Workflow, job, step ve runner

Workflow, otomatikleştirilmiş sürecin tamamını tanımlayan YAML dosyasıdır. Bir veya daha fazla job (iş) içerir. Job, aynı runner üzerinde çalışan bir adımlar dizisidir; varsayılan olarak job'lar birbirine paralel çalışır, ancak bağımlılık tanımlayarak sıralı da çalıştırabilirsiniz. Step (adım), bir job içindeki tekil işlemdir; ya bir kabuk komutu çalıştırır ya da hazır bir "action" kullanır. Runner ise workflow'un üzerinde çalıştığı sanal makinedir; GitHub'ın sağladığı Ubuntu, Windows veya macOS runner'larını kullanabilir ya da kendi runner'ınızı bağlayabilirsiniz.

Bir workflow'u tetikleyen şey ise olaylardır (events). En yaygın tetikleyici, bir dala kod gönderilmesi (push) veya bir pull request açılmasıdır. Bu olay tabanlı yapı, doğru süreçleri doğru anda otomatik olarak başlatmanızı sağlar.

İlk workflow dosyanızı oluşturmak

En basit haliyle, her push olduğunda bir mesaj yazdıran bir workflow ile başlayalım. Projenizde .github/workflows/ilk.yml dosyasını oluşturun:

name: İlk Pipeline
on: [push]
jobs:
  merhaba:
    runs-on: ubuntu-latest
    steps:
      - name: Selam ver
        run: echo "Pipeline calisiyor"

Bu kısa dosya temel yapıyı gösterir. name workflow'un adıdır. on tetikleyiciyi belirtir; burada her push'ta çalışır. jobs altında merhaba adında bir job tanımladık, bu job en güncel Ubuntu runner'ında çalışır ve tek bir adımda bir mesaj yazdırır. Bu dosyayı depoya gönderdiğinizde, GitHub deposunun "Actions" sekmesinde çalıştığını anında görürsünüz. Artık temeli kurduğumuza göre, gerçek bir test pipeline'ına geçebiliriz.

Adım 1: Otomatik test pipeline'ı kurmak

CI'nin kalbi otomatik testlerdir. Amaç, her kod değişikliğinin otomatik olarak kurulup test edilmesi ve hatalı kodun ana dala karışmadan yakalanmasıdır. Node.js bir proje için tipik bir test workflow'u şöyle görünür:

name: Test
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Kodu cek
        uses: actions/checkout@v4
      - name: Node kur
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"
      - name: Bagimliliklari yukle
        run: npm ci
      - name: Lint kontrolu
        run: npm run lint
      - name: Testleri calistir
        run: npm test

Bu workflow'u adım adım okuyalım. on bölümünde, hem main ve develop dallarına push'ta hem de main'e açılan pull request'lerde çalışacak şekilde ayarladık. Bu, hatalı kodun daha birleştirilmeden yakalanmasını sağlar. actions/checkout adımı depo kodunu runner'a indirir. actions/setup-node ile Node.js 20 kurulur ve npm önbelleği etkinleştirilir. Ardından npm ci ile bağımlılıklar temiz biçimde yüklenir, lint ve test komutları çalıştırılır. Herhangi bir adım başarısız olursa pipeline kırmızıya döner ve sorumlu geliştirici anında haberdar olur.

Birden fazla sürümde test etmek (matrix)

Eğer uygulamanızın farklı Node.js sürümlerinde çalıştığından emin olmak istiyorsanız, matrix stratejisi tam size göredir. Tek bir job tanımıyla, birden fazla ortamda paralel test çalıştırabilirsiniz:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: ["18", "20", "22"]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: [[ matrix.node ]]
      - run: npm ci
      - run: npm test

Bu yapı, üç farklı Node.js sürümü için aynı testleri paralel olarak çalıştırır. Kütüphane veya birden fazla ortamı desteklemesi gereken uygulamalar geliştiriyorsanız bu yaklaşım büyük zaman tasarrufu sağlar.

Adım 2: Build ve artefact üretimi

Testler geçtikten sonra sıra uygulamayı derlemeye gelir. Frontend uygulamalarında bu genellikle statik dosya üretimi, backend uygulamalarında ise derleme veya paketleme anlamına gelir. Üretilen çıktıyı (artefact) saklayıp sonraki job'larda kullanabilirsiniz.

jobs:
  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"
      - run: npm ci
      - name: Uygulamayi derle
        run: npm run build
      - name: Cikti dosyalarini sakla
        uses: actions/upload-artifact@v4
        with:
          name: derleme-ciktisi
          path: dist/

Burada dikkat edilmesi gereken anahtar satır "needs: test" ifadesidir. Bu, build job'unun yalnızca test job'u başarıyla tamamlandıktan sonra çalışmasını garanti eder. Böylece testten geçmeyen kodun asla derlenip dağıtılmamasını sağlamış olursunuz. upload-artifact adımı ise derleme çıktısını saklar; bu çıktıyı daha sonra dağıtım job'unda indirebilirsiniz.

Adım 3: Docker imajı build edip registry'ye göndermek

Modern dağıtımların çoğu container tabanlıdır. Uygulamanızı bir Docker imajına paketleyip bir registry'ye gönderdiğinizde, herhangi bir ortamda tutarlı biçimde çalıştırabilirsiniz. Container'ların CI/CD ile neden bu kadar iyi örtüştüğünü merak ediyorsanız Docker ile containerizasyon yazımız konuyu derinlemesine ele alıyor.

Aşağıdaki workflow, kodu çeker, Docker Hub'a giriş yapar, imajı build eder ve gönderir. Burada gizli bilgileri (secrets) ilk kez kullanıyoruz; bu değerleri depo ayarlarından güvenle tanımlayacağız (bir sonraki bölümde ayrıntılı anlatacağız).

name: Docker Build
on:
  push:
    branches: [main]
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Docker Hub girisi
        uses: docker/login-action@v3
        with:
          username: [[ secrets.DOCKERHUB_KULLANICI ]]
          password: [[ secrets.DOCKERHUB_TOKEN ]]
      - name: Imaji build et ve gonder
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: kullaniciadi/uygulamam:latest

Bu workflow main dalına her push'ta çalışır. docker/login-action ile registry'ye kimlik doğrulaması yapılır; kullanıcı adı ve token, depo secrets'ından çekilir. docker/build-push-action ise Dockerfile'ı kullanarak imajı oluşturur ve etiketleyip gönderir. Üretim ortamında "latest" yerine sürüm numarası veya commit kimliği gibi sabit etiketler kullanmanızı öneririz; bu, hangi sürümün canlıda olduğunu kesin biçimde takip etmenizi sağlar.

Container imajlarının registry üzerinden dağıtımını temsil eden görsel

Adım 4: Sunucuya otomatik dağıtım

İmaj registry'de hazır olduğunda, son adım onu hedef sunucuda çalıştırmaktır. En yaygın yöntemlerden biri, SSH üzerinden sunucuya bağlanıp yeni imajı çekmek ve container'ı yeniden başlatmaktır. Aşağıdaki workflow bu akışı gösterir:

name: Dagitim
on:
  push:
    branches: [main]
jobs:
  deploy:
    needs: docker
    runs-on: ubuntu-latest
    steps:
      - name: Sunucuya baglan ve dagit
        uses: appleboy/ssh-action@v1
        with:
          host: [[ secrets.SUNUCU_HOST ]]
          username: [[ secrets.SUNUCU_KULLANICI ]]
          key: [[ secrets.SUNUCU_SSH_ANAHTARI ]]
          script: |
            docker pull kullaniciadi/uygulamam:latest
            docker stop uygulamam || true
            docker rm uygulamam || true
            docker run -d --name uygulamam -p 80:3000 kullaniciadi/uygulamam:latest

Bu job, docker job'una bağımlıdır (needs: docker), yani yalnızca imaj başarıyla gönderildikten sonra çalışır. appleboy/ssh-action, secrets'ta tanımlı bağlantı bilgileriyle sunucuya bağlanır ve script bölümündeki komutları sırayla çalıştırır: yeni imajı çeker, eski container'ı durdurup kaldırır, yeni container'ı başlatır. "|| true" ifadeleri, container ilk kez çalıştırılıyorsa durdurma komutlarının hatayla pipeline'ı kırmasını önler.

Bu basit yaklaşım küçük ve orta projeler için yeterlidir. Ancak sıfır kesintili dağıtım, otomatik geri alma ve yatay ölçekleme gibi kurumsal ihtiyaçlar için Kubernetes gibi orkestrasyon araçlarına geçmek gerekir. Hangi altyapının size uygun olduğuna karar verirken bulut altyapısı nasıl seçilir yazımız yardımcı olacaktır.

Gizli bilgileri (secrets) güvenle yönetmek

Pipeline'larda en sık yapılan ciddi güvenlik hatası, şifre, token ve SSH anahtarı gibi hassas bilgileri doğrudan workflow dosyasına yazmaktır. Bu bilgiler asla depoya, hatta özel depoya bile düz metin olarak yazılmamalıdır. GitHub bunun için yerleşik bir secrets mekanizması sunar.

Bir gizli bilgi tanımlamak için deponuzun Settings bölümüne gidin, "Secrets and variables" altında "Actions" seçeneğini açın ve "New repository secret" ile değeri ekleyin. Tanımladığınız bu değerlere workflow içinde, az önce örneklerde gösterdiğimiz ifade söz dizimiyle erişirsiniz. GitHub bu değerleri günlüklerde otomatik olarak maskeler, yani yanlışlıkla ekrana yazdırsanız bile gerçek değer görünmez.

Secrets yönetiminde dikkat edilmesi gereken bazı temel kurallar şunlardır:

  • Her gizli bilgiyi yalnızca ihtiyaç duyan ortamda ve job'da kullanın.
  • Token'lara mümkün olan en dar yetkiyi verin; tam erişimli anahtarlardan kaçının.
  • Üretim ve test ortamları için ayrı secrets seti tutun.
  • Secrets değerlerini düzenli aralıklarla yenileyin (rotasyon).
  • Organizasyon seviyesinde paylaşılan secrets'ı yalnızca güvendiğiniz depolarla paylaşın.

Çoklu ortam stratejisi: staging ve production

Olgun bir CI/CD kurulumu, kodu doğrudan canlıya göndermez. Önce bir ön üretim (staging) ortamına dağıtır, orada doğrular, ardından production'a geçer. GitHub Actions'ın "environments" özelliği bu akışı yönetmek için idealdir; her ortam için ayrı secrets ve onay kuralları tanımlayabilirsiniz.

jobs:
  staging-dagitim:
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - run: echo "Staging ortamina dagitiliyor"
  production-dagitim:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - run: echo "Production ortamina dagitiliyor"

Burada koşullu çalışma (if) ile dal bazlı yönlendirme yaptık: develop dalı staging'e, main dalı production'a gider. environment olarak "production" tanımladığınızda, GitHub ayarlarından bu ortama dağıtımdan önce manuel onay zorunluluğu ekleyebilirsiniz. Bu, canlıya çıkmadan önce bir insanın "evet" demesini gerektiren ek bir güvenlik katmanı oluşturur. Ortam bazlı strateji, hız ile kontrol arasında doğru dengeyi kurmanın en temiz yoludur.

Pipeline'ı hızlandırmak: önbellek ve paralel job'lar

Bir CI/CD hattının değeri, hızıyla doğru orantılıdır. Her commit'te on dakika bekleten bir pipeline, geliştiricilerin akışını bozar ve zamanla görmezden gelinmeye başlar. Neyse ki pipeline'ları hızlandırmanın etkili yolları var.

İlk ve en etkili yöntem önbelleklemedir. Bağımlılıkların her seferinde sıfırdan indirilmesi büyük zaman kaybıdır. setup-node action'ının "cache" seçeneği bunu otomatik halleder, ancak daha ince kontrol için actions/cache kullanabilirsiniz:

- name: Bagimliliklari onbellekle
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-[[ hashFiles('package-lock.json') ]]
    restore-keys: npm-

İkinci yöntem paralelleştirmedir. Birbirine bağımlı olmayan job'ları paralel çalıştırmak toplam süreyi kısaltır; örneğin lint, birim testleri ve güvenlik taraması aynı anda yürütülebilir. Üçüncü yöntem ise gereksiz çalışmalardan kaçınmaktır: yalnızca dokümantasyon değiştiğinde tüm test paketini çalıştırmak gereksizdir; "paths" filtresiyle hangi dosya değişikliklerinin hangi workflow'u tetikleyeceğini sınırlayabilirsiniz.

Sık karşılaşılan hatalar ve çözümleri

Pipeline kurarken hemen herkesin takıldığı belirli noktalar vardır. Aşağıdaki tablo, sahada en sık karşılaştığımız sorunları ve çözümlerini özetliyor.

SorunOlası SebepÇözüm
Workflow hiç çalışmıyorDosya yanlış dizindeDosyayı .github/workflows altına koyun
Yerelde geçen test CI'da kalıyorOrtam değişkeni eksikEksik değişkenleri secrets/env olarak tanımlayın
Secrets değeri boş geliyorYanlış isim veya yetkiİsmi birebir kontrol edin, ortam erişimini doğrulayın
Pipeline çok yavaşÖnbellek yokBağımlılık önbelleğini etkinleştirin
Dağıtım yarıda kesiliyorSSH/yetki hatasıAnahtarı ve sunucu erişimini test edin
Yanlış dalda dağıtımEksik koşul (if)Dal bazlı koşulları net tanımlayın

Bu sorunların çoğu, ilk kurulumda küçük yapılandırma hatalarından kaynaklanır. Pipeline kurulduktan sonra düzenli izleme ve bakım, bu tür sorunların kalıcı olmasını önler; bakım, izleme ve destek hizmetlerimiz bu sürekliliği sağlamak için tasarlandı. CI/CD'nin ardındaki stratejik mantığı ve iş değerini bütünsel olarak değerlendirmek isteyenler için CI/CD pipeline'ının önemi yazımız iyi bir tamamlayıcıdır.

Sıkça Sorulan Sorular

GitHub Actions ücretsiz mi?

Genel (public) depolarda GitHub Actions çoğunlukla ücretsizdir. Özel depolarda ise aylık belirli bir ücretsiz çalışma dakikası kotası verilir; bu kotayı aşarsanız kullanım başına ücretlendirilirsiniz. Çoğu küçük ve orta ölçekli proje için ücretsiz kota fazlasıyla yeterli olur. Yoğun build ihtiyacı olan ekipler kendi runner'larını bağlayarak maliyeti kontrol altında tutabilir.

Kendi sunucumda runner çalıştırabilir miyim?

Evet. GitHub'ın barındırdığı runner'lar yerine kendi makinenizi "self-hosted runner" olarak bağlayabilirsiniz. Bu yaklaşım, özel donanım gerektiren işlerde, dakika maliyetini düşürmek isteyenlerde veya iç ağa erişim gereken dağıtımlarda tercih edilir. Ancak kendi runner'ınızın güvenliğinden ve bakımından siz sorumlu olursunuz.

GitHub Actions'tan başka bir CI/CD aracına geçmek zor mu?

Workflow mantığı tüm CI/CD araçlarında benzerdir; aşamalar, job'lar ve adımlar her yerde vardır. GitHub Actions YAML söz dizimi platforma özeldir, dolayısıyla başka bir araca geçerken bu dosyaları yeniden yazmanız gerekir. Ancak temel pipeline tasarımınız ve test/build/deploy mantığınız taşınabilir kalır, bu da geçişi yönetilebilir kılar.

Pipeline başarısız olduğunda ekip nasıl haberdar olur?

GitHub varsayılan olarak başarısız çalışmalar için e-posta bildirimi gönderir. Bunun ötesinde, Slack, Microsoft Teams veya e-posta entegrasyonlarıyla ekibinize anında bildirim gidecek adımlar ekleyebilirsiniz. Pull request akışında ise başarısız bir kontrol, kodun birleştirilmesini otomatik olarak engelleyecek şekilde yapılandırılabilir.

Veritabanı migrasyonlarını pipeline'a nasıl eklerim?

Migrasyonlar dağıtım adımının bir parçası olarak, ancak uygulama yeni sürümü ayağa kalkmadan önce çalıştırılmalıdır. Tipik olarak, dağıtım job'una migrasyon komutunu ayrı bir adım olarak eklersiniz. Geriye dönük uyumlu migrasyonlar yazmak, sıfır kesintili dağıtımın ön koşuludur; aksi halde eski ve yeni sürüm aynı anda çalışırken sorun yaşanabilir.

Sonuç

GitHub Actions ile CI/CD pipeline kurmak, ayrı bir altyapı yönetmeden, doğrudan kod deponuzun içinde profesyonel bir otomasyon hattı çalıştırmanızı sağlar. Bu yazıda otomatik testten Docker imajı üretimine, sunucuya dağıtımdan çoklu ortam stratejisine kadar uçtan uca bir kurulumu adım adım kurduk. Başlangıç olarak basit bir test workflow'u ile başlayıp, kademeli olarak build, container ve dağıtım adımlarını eklemek, en sağlıklı yaklaşımdır. Önbellekleme ve paralelleştirme ile pipeline'ı hızlı tutmak, secrets'ı doğru yönetmek ve çoklu ortam stratejisiyle kontrolü elde tutmak ise olgun bir kurulumun işaretleridir.

KaliteliWebsite olarak İstanbul'dan tüm Türkiye'ye, GitHub Actions ve diğer CI/CD araçlarıyla pipeline kurulumu, mevcut projelerin otomasyona taşınması, container tabanlı dağıtım ve bulut altyapısı entegrasyonu konularında uçtan uca hizmet veriyoruz. İster sıfırdan bir hat kuralım, ister mevcut sürecinizi optimize edelim; ekibinize hem teknik kurulumu hem de bilgi aktarımını sağlıyoruz. Modern bir web geliştirme ve bulut/DevOps altyapısı için 10.000 TL'den başlayan fiyatlarla ve ücretsiz keşif görüşmesiyle yanınızdayız. Dağıtım süreçlerinizi otomatikleştirmek için bugün bizimle iletişime geçin.

İlgili Yazılar