DEVOPS // CI/CDD::03 ORTA
22m READCOMPLETION: 82%ID::DOP-201

GITHUB ACTIONS İLE CI/CD PİPELINE

Workflow tasarımı, matrix build, Docker push ve sunucu deploy

GitHub Actions, depo değişikliklerine tepki veren otomatik iş akışları oluşturmanızı sağlar. Kod push'landığında test çalıştırmak, Docker image build etmek veya sunucuya deploy etmek için kurulum gerektirmeden CI/CD pipeline oluşturabilirsiniz.

İlk Workflow

// YAML //
# .github/workflows/ci.yml
name: CI Pipeline
 
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
 
jobs:
  test:
    runs-on: ubuntu-latest
 
    steps:
      - name: Kodu çek
        uses: actions/checkout@v4
 
      - name: Node.js kur
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'
 
      - name: Bağımlılıkları yükle
        run: npm ci
 
      - name: Lint kontrolü
        run: npm run lint
 
      - name: Tip kontrolü
        run: npm run type-check
 
      - name: Testleri çalıştır
        run: npm test -- --coverage
 
      - name: Coverage raporunu yükle
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

Matrix Build — Çoklu Ortam

// YAML //
jobs:
  test:
    runs-on: ${{ matrix.os }}
 
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node: ['20', '22']
      fail-fast: false  # Bir kombinasyon başarısız olsa diğerleri devam eder
 
    steps:
      - uses: actions/checkout@v4
 
      - name: Node ${{ matrix.node }} kurulumu
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
 
      - run: npm ci && npm test

Docker Build ve Push

// YAML //
# .github/workflows/docker.yml
name: Docker Build & Deploy
 
on:
  push:
    branches: [main]
    tags: ['v*']
 
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
 
jobs:
  build-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
 
    steps:
      - uses: actions/checkout@v4
 
      - name: Docker meta bilgisi
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=sha,prefix=sha-
            type=semver,pattern={{version}}
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
 
      - name: GitHub Container Registry'e giriş
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
 
      - name: Docker Buildx kur
        uses: docker/setup-buildx-action@v3
 
      - name: Build ve Push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha      # GitHub Actions cache
          cache-to:   type=gha,mode=max
          platforms: linux/amd64,linux/arm64

Veritabanı ile Entegrasyon Testleri

// YAML //
jobs:
  integration-test:
    runs-on: ubuntu-latest
 
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_USER:     test
          POSTGRES_PASSWORD: test
          POSTGRES_DB:       testdb
        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
      - uses: actions/setup-node@v4
        with: { node-version: '22', cache: 'npm' }
 
      - run: npm ci
 
      - name: Migration çalıştır
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/testdb
        run: npx prisma db push
 
      - name: Entegrasyon testleri
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/testdb
          REDIS_URL:    redis://localhost:6379
        run: npm run test:integration

Deploy — SSH ile Sunucu

// YAML //
jobs:
  deploy:
    runs-on: ubuntu-latest
    needs: [test, build-push]  # Önce testler ve build geçmeli
    if: github.ref == 'refs/heads/main'
 
    environment:
      name: production
      url: https://blog.example.com
 
    steps:
      - name: Sunucuya SSH ile bağlan ve deploy et
        uses: appleboy/ssh-action@v1
        with:
          host:     ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key:      ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/blog
            docker compose pull app
            docker compose up -d --no-deps app
            docker system prune -f
            echo "Deploy tamamlandı: $(date)"
 
      - name: Health check
        run: |
          sleep 10
          curl -f https://blog.example.com/health || exit 1

Güvenlik Taraması

// YAML //
jobs:
  security:
    runs-on: ubuntu-latest
 
    steps:
      - uses: actions/checkout@v4
 
      - name: Bağımlılık güvenlik taraması
        run: npm audit --audit-level=high
 
      - name: SAST — CodeQL analizi
        uses: github/codeql-action/init@v3
        with:
          languages: javascript, typescript
 
      - uses: github/codeql-action/autobuild@v3
 
      - uses: github/codeql-action/analyze@v3
 
      - name: Docker image güvenlik taraması
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'ghcr.io/${{ github.repository }}:latest'
          format: 'table'
          exit-code: '1'
          severity: 'CRITICAL,HIGH'

Gizli Değişken Yönetimi

// YAML //
# ASLA workflow içine direkt yazma:
# password: "super-secret"  ← YANLIŞ, git geçmişinde kalır!
 
# Doğru yöntem:
# GitHub → Settings → Secrets and Variables → Actions → New secret
 
jobs:
  deploy:
    steps:
      - name: Ortam değişkenlerini kullan
        env:
          DB_URL:     ${{ secrets.DATABASE_URL }}
          JWT_SECRET: ${{ secrets.JWT_SECRET }}
        run: npm start
 
      # Environment-specific secrets
      - name: Production secret
        if: github.ref == 'refs/heads/main'
        env:
          API_KEY: ${{ secrets.PROD_API_KEY }}
        run: echo "Production deploy"

Reusable Workflow

// YAML //
# .github/workflows/reusable-test.yml — paylaşılabilir workflow
on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
    secrets:
      DB_URL:
        required: true
 
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci && npm test
        env:
          DATABASE_URL: ${{ secrets.DB_URL }}
 
# Kullanan workflow
jobs:
  run-tests:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '22'
    secrets:
      DB_URL: ${{ secrets.DATABASE_URL }}

Sonuç

GitHub Actions ile tam CI/CD pipeline: otomatik test, Docker build, güvenlik taraması ve sunucu deploy — her commit'te güvenle çalışır. Matrix build ile çoklu ortam desteği, reusable workflow ile kod tekrarını önleyin. secrets ile hassas bilgileri koruyun ve environment ile production deploy'ları onay mekanizmasına bağlayın. Bir sonraki derste Kubernetes ile container orchestration konusunu ele alacağız.