GitHub Actions Nedir: CI/CD Temelleri ve Kullanımı
Yazılım geliştirme süreçlerinde en can sıkıcı şeylerden biri, her değişikliği elle test edip elle sunucuya atmaktır. Bir ara ben de bu döngüdeyim: kodu yaz, FTP’ye bağlan, dosyaları sürükle, sunucuya gir, servisi yeniden başlat… Hem zaman kaybı, hem de insan hatasına açık kapı. İşte tam da bu noktada CI/CD kavramı ve GitHub Actions devreye giriyor. Bu yazıda GitHub Actions’ı sıfırdan anlayacak, gerçek dünya senaryolarıyla nasıl kullanacağınızı öğreneceksiniz.
CI/CD Nedir, Neden Önemlidir
CI/CD, Continuous Integration (Sürekli Entegrasyon) ve Continuous Deployment/Delivery (Sürekli Dağıtım) kavramlarının birleşiminden oluşur.
Continuous Integration şu anlama gelir: Ekibinizdeki geliştiriciler kod yazdıkça, bu kodlar otomatik olarak ana dal ile birleştirilir ve her birleştirmede testler çalıştırılır. “Bende çalışıyordu” sorunu böylece ortadan kalkar.
Continuous Deployment/Delivery ise şunu ifade eder: Testleri geçen kod otomatik olarak staging veya production ortamına aktarılır. Siz kahve içerken sistem kendi kendine deploy eder.
Bu iki kavramın sağladığı faydalar oldukça somuttur:
- Hataları erken yakalar, production’a ulaşmadan önce görürsünüz
- Manuel işlemler azaldığı için insan hatası riski düşer
- Ekip üyeleri birbirinin kodunu sürekli entegre ettiğinden büyük merge çatışmaları yaşanmaz
- Yeni özellikler kullanıcılara daha hızlı ulaşır
- Gece 2’de sunucuya bağlanıp güncelleme yapma dönemi sona erer
GitHub Actions Nedir
GitHub Actions, GitHub’ın kendi bünyesinde sunduğu bir CI/CD platformudur. Deponuzda belirli olaylar (push, pull request, zamanlama vb.) gerçekleştiğinde otomatik olarak iş akışları başlatır. 2018’de beta olarak çıktı, 2019’da genel kullanıma açıldı ve şu an piyasadaki en popüler CI/CD araçlarından biri haline geldi.
GitHub Actions’ın öne çıkan özellikleri şunlardır:
- Ücretsiz kota: Public repolar için tamamen ücretsiz, private repolar için aylık 2000 dakika ücretsiz kullanım hakkı var
- Kolay entegrasyon: Zaten GitHub kullanıyorsanız ekstra bir servis kurmaya gerek yok
- Marketplace: Binlerce hazır action var, sıfırdan yazmak zorunda kalmıyorsunuz
- Matrix build: Aynı kodu farklı ortamlarda (Python 3.9, 3.10, 3.11 gibi) paralel test edebilirsiniz
- Self-hosted runner: Kendi sunucunuzda çalıştırabilirsiniz
Temel Kavramlar
GitHub Actions’ı anlamak için birkaç temel kavramı kafanıza oturtmanız gerekiyor.
Workflow (İş Akışı): Otomatikleştirmek istediğiniz sürecin tamamı. YAML formatında tanımlanır ve .github/workflows/ dizininde saklanır.
Event (Olay): Workflow’u tetikleyen şeydir. Bir branch’e push yapmak, pull request açmak, bir issue oluşturmak ya da belirli bir saatte zamanlama gibi durumlar birer event’tir.
Job (İş): Workflow içindeki adım gruplarıdır. Birden fazla job tanımlayabilirsiniz, bunlar paralel ya da sıralı çalışabilir.
Step (Adım): Bir job içindeki tek tek komutlardır. Her step ya bir shell komutu ya da hazır bir action çalıştırır.
Runner: Job’ların çalıştığı sanal makinedir. GitHub’ın kendi runner’ları Ubuntu, Windows ve macOS destekler.
Action: Tekrar kullanılabilir görev birimidir. Marketplace’ten hazır action’lar kullanabilir ya da kendi action’ınızı yazabilirsiniz.
İlk Workflow Dosyanızı Oluşturun
Hadi işe koyulalım. Basit bir Python projesi için ilk CI pipeline’ınızı oluşturalım. Deponuzda .github/workflows/ dizini yoksa oluşturun ve içine ci.yml adında bir dosya koyun.
mkdir -p .github/workflows
touch .github/workflows/ci.yml
İşte temel bir workflow dosyası:
# .github/workflows/ci.yml
name: Python CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Kodu çek
uses: actions/checkout@v4
- name: Python kur
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Bağımlılıkları yükle
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Testleri çalıştır
run: |
python -m pytest tests/ -v
- name: Kod kalitesini kontrol et
run: |
pip install flake8
flake8 . --count --max-line-length=127
Bu workflow ne yapıyor? main veya develop branch’ine push yapıldığında ya da main‘e pull request açıldığında tetikleniyor. Ubuntu üzerinde Python 3.11 kuruyor, bağımlılıkları yüklüyor, testleri çalıştırıyor ve kod kalitesini kontrol ediyor. Böyle basit bir dosya ile çok ciddi bir güvence elde ediyorsunuz.
Gerçek Dünya Senaryosu: Node.js Uygulaması Deploy
Diyelim ki bir Node.js web uygulamanız var ve her push’ta hem test etmek hem de DigitalOcean’daki sunucunuza otomatik deploy yapmak istiyorsunuz. İşte bunun için gerçekçi bir workflow:
# .github/workflows/deploy.yml
name: Test ve Deploy
on:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Node.js kur
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Paketleri yükle
run: npm ci
- name: Unit testleri çalıştır
run: npm test
- name: Build al
run: npm run build
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: SSH ile sunucuya bağlan ve deploy et
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/myapp
git pull origin main
npm ci --production
pm2 restart myapp
Burada dikkat etmeniz gereken birkaç nokta var. needs: test satırı, deploy job’ının ancak test job’ı başarıyla tamamlandıktan sonra çalışmasını sağlıyor. if: github.ref == 'refs/heads/main' koşulu ise deploy’un sadece main branch’inden tetiklenmesini garantiliyor. Secrets (gizli değişkenler) konusuna birazdan geleceğiz.
Secrets Yönetimi
Şifreler, API anahtarları ve SSH private key’leri gibi hassas bilgileri asla doğrudan YAML dosyasına yazmayın. GitHub’ın Secrets özelliği tam bu iş için var.
Secrets eklemek için şu adımları izleyin:
- GitHub deponuza gidin
- Settings sekmesine tıklayın
- Sol menüden “Secrets and variables” > “Actions” seçin
- “New repository secret” butonuna tıklayın
- İsim ve değer girerek kaydedin
Workflow dosyasında ise şu sözdizimini kullanıyorsunuz:
# Secrets kullanım örneği
steps:
- name: Docker Hub'a giriş yap
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login
-u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Ortam değişkenlerini ayarla
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}
run: |
echo "Veritabanına bağlanılıyor..."
node scripts/migrate.js
Secrets log’larda otomatik olarak maskelenir. Yani echo ${{ secrets.MY_SECRET }} yazsanız bile çıktıda * görürsünüz. Bu güzel bir güvenlik önlemi.
Matrix Build ile Çoklu Ortam Testi
Bir kütüphane geliştiriyorsanız ya da uygulamanızın birden fazla Python/Node sürümüyle çalışmasını istiyorsanız matrix build hayat kurtarır. Tek bir workflow tanımı ile onlarca kombinasyonu paralel test edebilirsiniz:
# .github/workflows/matrix.yml
name: Çoklu Ortam Testi
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', '3.10', '3.11', '3.12']
exclude:
- os: windows-latest
python-version: '3.9'
steps:
- uses: actions/checkout@v4
- name: Python ${{ matrix.python-version }} kur
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Testleri çalıştır
run: |
pip install pytest
pytest tests/ -v --tb=short
Bu workflow, exclude kısmı hariç toplamda 11 farklı kombinasyonu paralel olarak çalıştırır. Eğer her birini elle test etseydiniz saatler harcardınız. GitHub Actions bunu dakikalar içinde halleder.
Artifact Yönetimi ve Önbellekleme
Her workflow çalışmasında bağımlılıkları sıfırdan indirmek zaman kaybıdır. Önbellekleme ile bu süreyi ciddi ölçüde kısaltabilirsiniz:
# .github/workflows/cache-example.yml
name: Önbellekli Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: npm önbelleğini ayarla
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Paketleri yükle
run: npm ci
- name: Build al
run: npm run build
- name: Build çıktısını artifact olarak sakla
uses: actions/upload-artifact@v3
with:
name: build-output
path: dist/
retention-days: 7
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Build artifact'ını indir
uses: actions/download-artifact@v3
with:
name: build-output
path: dist/
- name: Sunucuya yükle
run: |
rsync -avz dist/ user@server:/var/www/html/
hashFiles fonksiyonu, package-lock.json dosyasının hash’ini önbellek anahtarı olarak kullanır. Bağımlılıklar değişmediği sürece önbellekten yükleme yapılır, değişirse yeni bir önbellek oluşturulur. Bu küçük optimizasyon, workflow sürenizi yüzde elliye kadar düşürebilir.
Docker ile CI/CD Pipeline
Modern uygulamaların büyük çoğunluğu containerized olarak çalışıyor. Docker image build edip registry’ye push etmek ve ardından deploy etmek için şu workflow’u kullanabilirsiniz:
# .github/workflows/docker-deploy.yml
name: Docker Build ve Deploy
on:
push:
branches: [ main ]
tags: [ 'v*.*.*' ]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Docker Buildx kur
uses: docker/setup-buildx-action@v3
- name: Docker Hub'a giriş yap
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Meta bilgileri çıkar
id: meta
uses: docker/metadata-action@v5
with:
images: myusername/myapp
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Image'ı build et ve push et
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Uzak sunucuda container'ı güncelle
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker pull myusername/myapp:main
docker stop myapp || true
docker rm myapp || true
docker run -d
--name myapp
--restart unless-stopped
-p 3000:3000
-e DATABASE_URL=$DATABASE_URL
myusername/myapp:main
Tag push’larında (v1.2.3 gibi) otomatik olarak semantic versioning ile etiketleme yapılıyor. Bu sayede image geçmişiniz düzenli kalır ve gerektiğinde eski bir versiyona dönmek kolaylaşır.
Workflow Tetikleyicileri ve Koşullar
GitHub Actions’ın gücünün önemli bir kısmı esnek tetikleyici sistemidir. İhtiyacınıza göre şekillendirin:
# .github/workflows/advanced-triggers.yml
name: Gelişmiş Tetikleyiciler
on:
# Zamanlama ile çalıştır (her gece saat 02:00 UTC)
schedule:
- cron: '0 2 * * *'
# Manuel tetikleme (input parametreli)
workflow_dispatch:
inputs:
environment:
description: 'Deploy ortamı'
required: true
default: 'staging'
type: choice
options:
- staging
- production
debug_mode:
description: 'Debug modu aktif et'
type: boolean
default: false
# Başka bir workflow tamamlandığında
workflow_run:
workflows: ["Test Suite"]
types:
- completed
jobs:
conditional-deploy:
runs-on: ubuntu-latest
# Sadece başarılı workflow'dan sonra çalış
if: ${{ github.event.workflow_run.conclusion == 'success' }}
environment: ${{ inputs.environment || 'staging' }}
steps:
- name: Ortam bilgisini göster
run: |
echo "Deploy ortamı: ${{ inputs.environment }}"
echo "Debug modu: ${{ inputs.debug_mode }}"
echo "Tetikleyen: ${{ github.event_name }}"
Özellikle workflow_dispatch çok kullanışlı. GitHub arayüzünden “Run workflow” butonuna tıklayarak manuel olarak ve parametrelerle çalıştırabiliyorsunuz. Gece yarısı acil bir deploy yapmanız gerektiğinde terminale bile gerek kalmıyor.
Self-Hosted Runner Kurulumu
GitHub’ın sunduğu runner’lar çoğu iş için yeterlidir ancak bazı durumlarda kendi runner’ınızı kurmak mantıklıdır:
- Private network kaynaklarına erişmeniz gerekiyorsa
- Özel donanım gerektiren işler varsa
- Ücretsiz dakika kotasını aşıyorsanız
- Daha hızlı bir makine istiyorsanız
Runner kurmak için şu adımları izleyin:
# GitHub > Settings > Actions > Runners > New self-hosted runner
# Runner'ı indir
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.311.0.tar.gz -L
https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz
# Yapılandır (token GitHub arayüzünden alınır)
./config.sh --url https://github.com/KULLANICI/REPO
--token BURAYA_TOKEN_GELECEK
# Servis olarak kur ve başlat
sudo ./svc.sh install
sudo ./svc.sh start
# Durum kontrolü
sudo ./svc.sh status
Workflow dosyasında self-hosted runner kullanmak için runs-on satırını değiştirmeniz yeterli:
jobs:
build:
runs-on: self-hosted
# ya da daha spesifik etiket ile:
# runs-on: [self-hosted, linux, x64]
Hata Ayıklama ve İzleme
Workflow’larınızda bir şeyler ters gittiğinde ne yaparsınız? GitHub Actions birkaç güzel araç sunuyor:
# .github/workflows/debug.yml
name: Debug Pipeline
on: [push]
jobs:
debug-job:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Ortam değişkenlerini listele
run: env | sort
- name: GitHub context bilgisi
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Hata durumunda bile çalış
if: failure()
run: |
echo "Bir önceki adım başarısız oldu!"
echo "Branch: ${{ github.ref }}"
echo "Commit: ${{ github.sha }}"
# Slack bildirimi gönder
curl -X POST ${{ secrets.SLACK_WEBHOOK }}
-H 'Content-type: application/json'
--data '{"text":"Deploy başarısız! Branch: ${{ github.ref }}"}'
- name: Her durumda çalış
if: always()
run: echo "Bu adım her zaman çalışır"
if: failure() ile hata durumunda Slack veya e-posta bildirimi gönderebilirsiniz. if: always() ile log toplama veya temizleme işlemlerini her zaman çalıştırabilirsiniz.
Yaygın Hatalar ve Çözümleri
Yeni başlayanların en sık yaptığı hatalar şunlardır:
YAML girintileme hataları: YAML’da girinti hayati önem taşır. Tab yerine boşluk kullanın ve tutarlı olun. Visual Studio Code için YAML extension’ı kurmanızı öneririm.
Secrets’ı yanlış referanslama: ${{ secret.MY_KEY }} değil, ${{ secrets.MY_KEY }} doğru kullanım.
Job bağımlılıklarını unutmak: needs tanımlamadan deploy job’ı test job’ından önce çalışabilir.
Runner’da sudo gerektiren komutlar: GitHub’ın runner’larında sudo çalışır ancak self-hosted runner’larda kullanıcı yetkilerine dikkat edin.
Büyük artifact’lar: 500 MB’ı aşan artifact’lar için GitHub’ın artifact depolama limitlerini göz önünde bulundurun, harici storage kullanmayı düşünün.
Sonuç
GitHub Actions, yazılım geliştirme süreçlerinizi kökten dönüştürebilecek güçlü bir araçtır. Bu yazıda ele aldığımız konular bir başlangıç noktasıdır: temel CI pipeline’dan Docker deployment’a, matrix build’den self-hosted runner’a kadar oldukça geniş bir yelpaze gördünüz.
Benim tavsiyem şu: Karmaşık şeylerle başlamayın. Önce projenize basit bir test workflow’u ekleyin. Çalıştığını görünce bir adım daha atın, staging deploy’u ekleyin. Sonra production’ı otomatize edin. Her adımda güven kazanırsınız ve sistemi daha iyi anlarsınız.
CI/CD’nin en büyük katkısı teknik olmayan bir şeydir aslında: Zihinsel rahatlık. “Deploy ettim, bir şey bozuldu mu acaba?” kaygısıyla değil, “Testler geçti, otomatik deploy oldu, her şey yolunda” güveniyle çalışmak başka bir his. GitHub Actions ile bu noktaya ulaşmak artık hiç bu kadar kolay olmamıştı.
