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.
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.
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.
| Sorun | Olası Sebep | Çözüm |
|---|---|---|
| Workflow hiç çalışmıyor | Dosya yanlış dizinde | Dosyayı .github/workflows altına koyun |
| Yerelde geçen test CI'da kalıyor | Ortam değişkeni eksik | Eksik değişkenleri secrets/env olarak tanımlayın |
| Secrets değeri boş geliyor | Yanlış isim veya yetki | İsmi birebir kontrol edin, ortam erişimini doğrulayın |
| Pipeline çok yavaş | Önbellek yok | Bağımlılık önbelleğini etkinleştirin |
| Dağıtım yarıda kesiliyor | SSH/yetki hatası | Anahtarı ve sunucu erişimini test edin |
| Yanlış dalda dağıtım | Eksik 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
Docker ile containerizasyon: Modern geliştirme iş akışı
Docker nedir, nasıl çalışır? Container teknolojisi ve Dockerfile en iyi pratikleri.
Oku →2026-03-15CI/CD Pipeline'ının Önemi: Nasıl Kurulur ve Neden Gereklidir?
CI/CD neden gereklidir? Otomatik test, build ve deploy süreçleriyle geliştirme hızınızı nasıl artırırsınız?
Oku →