DevOps & Cloud
CI/CD Pipeline: GitHub Actions ile Otomatik Test ve Deployment
CI/CD (Continuous Integration / Continuous Deployment), yazilim gelistirme surecinin en kritik bilesenlerinden biridir. GitHub Actions, kod degisikliklerini otomatik olarak test eden, build eden ve deploy eden guclu bir CI/CD platformudur. Bu yazida GitHub Actions ile .NET ve Flutter projeleri icin kapsamli CI/CD pipeline'lari olusturmayi, otomatik deployment stratejilerini ve production-ready workflow yapilandirmalarini detayli olarak inceleyecegim.
Kendi projelerimde GitHub Actions'a gecis yaptigimdan beri manuel deployment hatalarini sifira indirdim. Her push'ta otomatik test, build ve deployment surecleri sayesinde hem gelistirme hizim artti hem de production ortaminin guvenilirligi yukseldi.
GitHub Actions Temelleri
Workflow Yapisi
GitHub Actions workflow'lari .github/workflows/ dizininde YAML dosyalari olarak tanimlanir. Her workflow bir veya daha fazla job icerir ve her job bir dizi step'ten olusur.
Temel kavramlar:
- Workflow: Otomatik surec tanimi (YAML dosyasi)
- Event: Workflow'u tetikleyen olay (push, pull_request, schedule)
- Job: Paralel veya sirali calisabilen is birimleri
- Step: Job icindeki tek bir islem adimi
- Action: Yeniden kullanilabilir is birimi (marketplace veya ozel)
.NET CI/CD Pipeline
Build, Test ve Deployment
# .github/workflows/dotnet-ci-cd.yml
name: .NET CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
DOTNET_VERSION: '8.0.x'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: testdb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- name: .NET SDK kur
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: NuGet paketlerini cache'le
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: nuget-
- name: Restore
run: dotnet restore
- name: Build
run: dotnet build --no-restore -c Release
- name: Unit testleri calistir
run: dotnet test --no-build -c Release --filter "Category!=Integration" --logger "trx;LogFileName=unit-tests.trx" --collect:"XPlat Code Coverage"
- name: Integration testleri calistir
run: dotnet test --no-build -c Release --filter "Category=Integration" --logger "trx;LogFileName=integration-tests.trx"
env:
ConnectionStrings__DefaultConnection: "Host=localhost;Database=testdb;Username=postgres;Password=postgres"
Redis__ConnectionString: "localhost:6379"
- name: Test sonuclarini yukle
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: "**/*.trx"
- name: Code coverage raporu
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
docker-build:
needs: build-and-test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Container registry'ye giris
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha
type=raw,value=latest
- name: Docker imaji build ve push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: docker-build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: SSH ile sunucuya deploy
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -fFlutter CI/CD Pipeline
Flutter Build ve Test
# .github/workflows/flutter-ci-cd.yml
name: Flutter CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
analyze-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Flutter SDK kur
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.0'
channel: stable
cache: true
- name: Bagimliliklari yukle
run: flutter pub get
- name: Kod analizi
run: flutter analyze --fatal-infos
- name: Testleri calistir
run: flutter test --coverage
- name: Coverage raporu
uses: codecov/codecov-action@v4
with:
file: coverage/lcov.info
build-android:
needs: analyze-and-test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Java kur
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Flutter SDK kur
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.0'
channel: stable
cache: true
- name: Keystore dosyasini decode et
run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > android/app/keystore.jks
- name: Android APK build
run: flutter build apk --release
env:
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
- name: APK artifact yukle
uses: actions/upload-artifact@v4
with:
name: android-release
path: build/app/outputs/flutter-apk/app-release.apk
build-ios:
needs: analyze-and-test
runs-on: macos-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Flutter SDK kur
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.0'
channel: stable
cache: true
- name: iOS build
run: flutter build ios --release --no-codesign
- name: IPA artifact yukle
uses: actions/upload-artifact@v4
with:
name: ios-release
path: build/ios/iphoneos/Runner.appIleri Seviye Workflow Teknikleri
Secrets Yonetimi ve Guvenlik
GitHub Actions'da hassas verilerin guvenli yonetimi icin cok katmanli bir yaklasim benimsenmalidir:
- Repository secrets: Tum workflow'larda kullanilabilen genel secretlar (API key'leri, token'lar)
- Environment secrets: Production, staging gibi ortam bazli secret yonetimi. Environment bazli approval zorunlulugu eklenebilir
- OIDC: AWS, Azure gibi cloud provider'lara secretsiz baglanmak icin OpenID Connect. Uzun omurlu credential'lar yerine kisa omurlu token'lar kullanir
# OIDC ile AWS'ye secretsiz erisim ornegi
permissions:
id-token: write
contents: read
steps:
- name: AWS credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions-role
aws-region: eu-central-1
- name: ECR'ye giris
uses: aws-actions/amazon-ecr-login@v2OIDC kullanarak static access key'leri tamamen ortadan kaldirabilirsiniz. Bu yontem ozellikle AWS ve Azure entegrasyonlarinda guvenlik acisindan en iyi pratik olarak kabul edilir.
Ortam Bazli Deployment
Farkli ortamlar icin farkli yapilandirmalar kullanmak, deployment guvenligini artirir:
# Staging ve production icin ayri deployment job'lari
deploy-staging:
needs: docker-build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
environment: staging
steps:
- name: Deploy to staging
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.STAGING_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/myapp-staging
docker compose pull
docker compose up -d --remove-orphans
deploy-production:
needs: docker-build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production # Manual approval gerektirir
steps:
- name: Deploy to production
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.PRODUCTION_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -fReusable Workflows
Tekrarlayan workflow parcalarini paylasabilir workflow'lara donusturun. Organizasyon genelinde standart CI/CD pratiklerini zorunlu kilmak icin cok etkilidir:
# .github/workflows/reusable-dotnet-build.yml
name: Reusable .NET Build
on:
workflow_call:
inputs:
dotnet-version:
required: true
type: string
project-path:
required: true
type: string
secrets:
CODECOV_TOKEN:
required: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ inputs.dotnet-version }}
- run: dotnet restore ${{ inputs.project-path }}
- run: dotnet build ${{ inputs.project-path }} --no-restore -c Release
- run: dotnet test ${{ inputs.project-path }} --no-build -c ReleaseMatrix Strategy
Birden fazla versiyon veya platform icin paralel test calistirmak icin matrix strategy kullanin:
# Matrix strategy ile coklu platform testi
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
dotnet-version: ['8.0.x', '9.0.x']
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ matrix.dotnet-version }}
- run: dotnet test -c ReleaseCaching Stratejileri
Build surelerini kisaltmak icin etkili cache stratejileri kullanin:
# Docker layer cache
- name: Docker build with cache
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
# NuGet package cache
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj') }}
restore-keys: |
nuget-${{ runner.os }}-
# Flutter pub cache
- uses: actions/cache@v4
with:
path: |
~/.pub-cache
.dart_tool
key: flutter-${{ hashFiles('**/pubspec.lock') }}Cache hit oranini izlemek ve cache key stratejinizi optimize etmek, build surelerini %50'ye kadar kisaltabilir. Ozellikle buyuk dependency'lere sahip projelerde cache kullanimi buyuk fark yaratir.
Pratik Oneriler ve Ozet
GitHub Actions ile CI/CD pipeline olusturulurken su noktalara dikkat edin:
- Cache kullanimi: NuGet, npm, Flutter paketlerini cache'leyerek build surelerini kisaltin
- Paralel job'lar: Bagimsiz islemleri paralel calistirarak toplam sureyi azaltin
- Environment koruma: Production deployment icin manual approval ekleyin
- Artifact yonetimi: Build ciktilarini artifact olarak saklayin, rollback icin hazir bulundurun
- Bildirimler: Slack veya Teams entegrasyonu ile pipeline durumunu takip edin
Iyi yapilandirilmis bir CI/CD pipeline, yazilim gelistirme surecinin omurgasidir. Otomatik test ve deployment sayesinde hem hata oranini dusurur hem de teslim hizini artirirsiniz.
İlgili Makaleler
.NET CI/CD: GitHub Actions ve Azure DevOps ile Otomatik Deployment
.NET projeleri için CI/CD pipeline tasarlayın. GitHub Actions, Azure DevOps ve deployment stratejileri.
AWS Bulut Altyapısı: EC2, S3, CloudFront ve Lambda Rehberi
AWS bulut hizmetlerini öğrenin. EC2 sunucu yönetimi, S3 dosya depolama, CloudFront CDN, Lambda serverless fonksiyonlar ve VPC ağ yapılandırması.
Docker Konteyner Rehberi: Dockerfile, Compose ve Multi-Stage Build
Docker ile konteynerleştirme rehberi. Dockerfile yazma, Docker Compose ile çoklu servis, multi-stage build optimizasyonu ve production deployment.
Flutter Projeniz mi Var?
iOS, Android ve web için yüksek performanslı Flutter uygulamaları geliştiriyorum.
İletişime Geç