CI/CD Pipeline Kurulumu: GitHub Actions ile Otomasyon
Yazılım geliştirme süreçlerinde en kritik adımlardan biri, kodun yazılmasından production ortamına ulaşmasına kadar geçen sürecin otomatikleştirilmesidir. CI/CD (Continuous Integration / Continuous Delivery) pipeline'ları bu süreci güvenilir, tekrarlanabilir ve hızlı hale getirir. GitHub Actions, GitHub ekosistemiyle doğal entegrasyonu sayesinde bu alanda en popüler araçlardan biri haline gelmiştir.
CI/CD Nedir ve Neden Önemlidir?
Continuous Integration (CI), geliştiricilerin kodlarını sık sık ana branch'e entegre etmesini ve her entegrasyonda otomatik testlerin çalıştırılmasını ifade eder. Continuous Delivery (CD) ise bu entegre edilmiş kodun otomatik olarak staging veya production ortamlarına dağıtılmasını sağlar.
CI/CD pipeline'ı olmayan bir projede şu sorunlarla karşılaşırsınız:
- Manuel test süreçleri nedeniyle hataların geç fark edilmesi
- Deployment işlemlerinin kişiye bağımlı olması ve tutarsızlıklar
- "Benim bilgisayarımda çalışıyor" sendromu
- Release süreçlerinin saatler hatta günler sürmesi
- Kod kalitesinin zaman içinde düşmesi
GitHub Actions'a Giriş
GitHub Actions, GitHub'ın yerleşik CI/CD çözümüdür. YAML dosyaları ile tanımlanan workflow'lar aracılığıyla, belirli olaylar (event) tetiklendiğinde otomatik işlemler çalıştırmanızı sağlar. Public repository'ler için ücretsizdir; private repository'lerde ise belirli bir kullanım kotası sunulur.
Temel kavramları şöyle özetleyebiliriz:
- Workflow: Otomatikleştirilmiş sürecin tamamını tanımlayan YAML dosyası
- Event: Workflow'u tetikleyen olay (push, pull request, schedule vb.)
- Job: Bir workflow içinde çalışan bağımsız iş birimi
- Step: Bir job içindeki her bir adım
- Action: Tekrar kullanılabilir, önceden tanımlanmış komut blokları
- Runner: Workflow'ların çalıştığı sanal makine ortamı
İlk Workflow Dosyasını Oluşturma
GitHub Actions workflow dosyaları, projenizin kök dizinindeki .github/workflows/ klasörü altında yer alır. Bir Node.js projesi için temel bir CI pipeline'ı oluşturarak başlayalım:
name: CI Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build-and-test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x, 22.x]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Build project
run: npm run build
Bu workflow dosyasını adım adım inceleyelim: on bloğu, workflow'un main ve develop branch'lerine push yapıldığında veya main branch'e pull request açıldığında tetikleneceğini belirtir. strategy.matrix ile aynı job'ı birden fazla Node.js versiyonunda paralel olarak çalıştırıyoruz. npm ci komutu, npm install'a göre daha hızlı ve deterministik bir kurulum sağlar çünkü package-lock.json dosyasını bire bir takip eder.
Kod Kalitesi ve Güvenlik Kontrolleri Ekleme
Temel CI pipeline'ını daha kapsamlı hale getirmek için kod kalitesi ve güvenlik taramalarını ekleyebilirsiniz:
code-quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Check code formatting
run: npx prettier --check .
- name: Run type checking
run: npx tsc --noEmit
- name: Run security audit
run: npm audit --audit-level=high
- name: Upload coverage report
if: success()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 7
Bu job, Prettier ile kod formatlama kontrolü, TypeScript tip kontrolü ve bağımlılıklardaki güvenlik açıklarını tarar. upload-artifact action'ı ile test coverage raporunu daha sonra indirebilmeniz için saklarsınız.
CD Pipeline: Otomatik Deployment
CI aşaması başarıyla tamamlandıktan sonra, kodun otomatik olarak deploy edilmesini sağlayacak bir CD pipeline'ı ekleyelim. Aşağıdaki örnek, Docker image'ı oluşturup bir container registry'ye push etmeyi ve ardından deployment tetiklemeyi gösterir:
deploy:
needs: [build-and-test, code-quality]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment:
name: production
url: https://myapp.example.com
steps:
- uses: actions/checkout@v4
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
- name: Deploy to production
run: |
curl -X POST \
-H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"image": "ghcr.io/${{ github.repository }}:${{ github.sha }}"}' \
https://api.example.com/deploy
needs alanı, bu job'ın ancak build-and-test ve code-quality job'ları başarılı olduktan sonra çalışacağını garanti eder. if koşulu ile deployment'ın yalnızca main branch'e yapılan push'larda tetiklenmesini sağlıyoruz. environment bloğu, GitHub'ın environment protection rules özelliğini devreye sokar; böylece production deployment'ları için onay mekanizması ekleyebilirsiniz.
Secret ve Ortam Değişkenleri Yönetimi
CI/CD pipeline'larında API anahtarları, token'lar ve parolalar gibi hassas bilgileri asla doğrudan workflow dosyasına yazmamalısınız. GitHub Actions bu konuda Secrets mekanizması sunar:
- Repository Secrets: Tek bir repository'ye özel gizli değerler. Settings → Secrets and variables → Actions altından tanımlanır.
- Environment Secrets: Belirli bir environment'a (staging, production) bağlı gizli değerler. Environment protection rules ile birlikte kullanılır.
- Organization Secrets: Organizasyon genelinde paylaşılan gizli değerler.
Workflow içinde bu değerlere ${{ secrets.SECRET_NAME }} sözdizimi ile erişirsiniz. GitHub Actions, log çıktılarında secret değerleri otomatik olarak maskeler.
Cache Kullanarak Pipeline Hızını Artırma
Bağımlılıkların her çalıştırmada sıfırdan indirilmesi pipeline süresini önemli ölçüde uzatır. Caching mekanizması bu sorunu çözer:
- name: Cache node modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
hashFiles fonksiyonu, package-lock.json dosyasının hash'ini alarak cache anahtarı oluşturur. Bağımlılıklar değişmediği sürece cache kullanılır, bu da build sürelerini dramatik biçimde kısaltır. Daha önce gösterdiğimiz actions/setup-node action'ındaki cache: 'npm' parametresi de benzer bir optimizasyonu otomatik olarak sağlar.
Branch Protection ve Status Check Entegrasyonu
CI pipeline'ının gerçek gücü, branch protection rules ile birleştiğinde ortaya çıkar. GitHub'da main branch'iniz için şu kuralları etkinleştirmeniz önerilir:
- Require status checks to pass before merging: Tanımladığınız CI job'larının başarılı olmasını zorunlu kılın.
- Require branches to be up to date: PR'ın merge edilmeden önce hedef branch ile güncel olmasını sağlayın.
- Require pull request reviews: En az bir kişinin kodu incelemesini zorunlu tutun.
- Do not allow bypassing the above settings: Yöneticiler dahil herkesin bu kurallara uymasını sağlayın.
Bu sayede main branch'e doğrudan push yapmak engellenir ve her değişiklik CI pipeline'ından geçmek zorunda kalır.
Reusable Workflow ve Composite Action Oluşturma
Birden fazla repository'de benzer pipeline'lar kullanıyorsanız, tekrarlayan kodu azaltmak için reusable workflow tanımlayabilirsiniz:
# .github/workflows/reusable-node-ci.yml
name: Reusable Node.js CI
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: '20.x'
secrets:
NPM_TOKEN:
required: false
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
- run: npm run build
Bu reusable workflow'u başka bir workflow'dan çağırmak için:
jobs:
call-ci:
uses: my-org/shared-workflows/.github/workflows/reusable-node-ci.yml@main
with:
node-version: '22.x'
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Pipeline İzleme ve Hata Ayıklama
Pipeline'lar zaman zaman başarısız olacaktır. Hata ayıklama sürecini kolaylaştırmak için birkaç strateji uygulayabilirsiniz:
- Bildirim entegrasyonu: Slack veya e-posta bildirimleri ile başarısız pipeline'lardan anında haberdar olun.
- Debug logging: Repository secrets'a
ACTIONS_RUNNER_DEBUGdeğerinitrueolarak ekleyerek ayrıntılı loglar etkinleştirin. - Artifact kaydetme: Başarısız testlerin log dosyalarını ve screenshot'larını artifact olarak saklayın.
- Timeout ayarlama: Sonsuz döngüye giren job'ların kaynak tüketmesini önlemek için
timeout-minutestanımlayın.
Slack bildirimi örneği:
- name: Notify Slack on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "CI Pipeline başarısız oldu: ${{ github.repository }}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Pipeline Hatası*\nRepo: ${{ github.repository }}\nBranch: ${{ github.ref_name }}\nCommit: ${{ github.sha }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
İyi Pratikler ve Öneriler
Yıllar içinde CI/CD pipeline'larıyla çalışırken edinilen deneyimlerden derlenen en önemli pratikler şunlardır:
- Pipeline'ı hızlı tutun: 10 dakikayı aşan pipeline'lar geliştirici deneyimini ciddi şekilde bozar. Paralel job'lar, caching ve gereksiz adımları kaldırarak süreyi optimize edin.
- Fail fast prensibi: En hızlı çalışan kontrolleri (lint, format) pipeline'ın başına koyun. Böylece basit hatalar erken yakalanır.
- Workflow dosyalarını versiyonlayın: Workflow değişiklikleri de kod gibi PR sürecinden geçmeli ve review edilmelidir.
- Action versiyonlarını pinleyin:
uses: actions/checkout@v4yerine tam commit SHA kullanmak güvenlik açısından daha sağlamdır. - Minimum yetki prensibi:
permissionsbloğuyla workflow'a yalnızca ihtiyaç duyduğu yetkileri verin. - Concurrency kontrolü: Aynı branch için birden fazla pipeline'ın gereksiz yere çalışmasını engellemek için
concurrencyayarını kullanın.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Bu ayar, aynı branch'te yeni bir push yapıldığında önceki çalışan pipeline'ı iptal eder ve sadece en güncel kodu test eder.
Sonuç
GitHub Actions ile CI/CD pipeline kurulumu, modern yazılım geliştirme süreçlerinin vazgeçilmez bir parçasıdır. Doğru yapılandırılmış bir pipeline; hataları erken yakalar, deployment süreçlerini güvenilir kılar ve ekibin kod kalitesine olan güvenini artırır. Küçük başlayıp ihtiyaçlarınız doğrultusunda pipeline'ınızı genişletmeniz, sürdürülebilir ve bakımı kolay bir otomasyon altyapısı oluşturmanın en sağlıklı yoludur. Unutmayın: en iyi pipeline, ekibinizin gerçek ihtiyaçlarına cevap veren ve sürekli iyileştirilen pipeline'dır.