Ana içeriğe geç
Kategoriye Dön

GitHub Actions ile Otomatik Deployment: CI/CD Pipeline Kurulumu

GitHub Actions ile CI/CD pipeline oluşturma, Docker build ve push, SSH ile sunucuya deployment, test otomasyonu, secrets yönetimi ve workflow optimizasyonu.

Okuma süresi: 18 dk DevOps & Otomasyon
github-actionsci/cddeploymentdevopsotomasyondockerssh

İçindekiler

GitHub Actions ile Otomatik Deployment: CI/CD Pipeline Kurulumu

GitHub Actions, kod değişikliklerini otomatik olarak test eden, derleyen ve sunucuya deploy eden güçlü bir CI/CD platformudur. Bu rehberde sıfırdan production-ready bir pipeline kuracağız.

GitHub Actions Nedir?

GitHub Actions, GitHub deposuna entegre bir otomasyon platformudur:

  • Push, PR, schedule gibi olaylara tepki verir
  • Paralel ve sıralı iş akışları çalıştırır
  • 2.000 dakika/ay ücretsiz (public repo'lar sınırsız)
  • Binlerce hazır action ile genişletilebilir

GitHub Actions workflow dosyaları .github/workflows/ dizininde YAML formatında saklanır.

Temel Workflow Yapısı

hljs yaml
# .github/workflows/deploy.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Node.js kurulumu
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      - name: Bağımlılıkları yükle
        run: npm ci
      - name: Testleri çalıştır
        run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - name: Deploy et
        run: echo "Deploy adımları burada"

on / jobs / steps Yapısı

Tetikleyiciler (on)

hljs yaml
on:
  # Branch'e push
  push:
    branches: [main, develop]
    paths:
      - 'src/**'
      - 'package.json'

  # Pull request
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]

  # Zamanlanmış çalışma (cron)
  schedule:
    - cron: '0 2 * * *'  # Her gece 02:00

  # Manuel tetikleme
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deploy ortamı'
        required: true
        default: 'staging'
        type: choice
        options: [staging, production]

  # Başka workflow tamamlandığında
  workflow_run:
    workflows: ["Build"]
    types: [completed]

Job Yapılandırması

hljs yaml
jobs:
  build:
    runs-on: ubuntu-latest
    # Ortam değişkenleri
    env:
      NODE_ENV: test
    # Zaman aşımı (dakika)
    timeout-minutes: 30
    # Strateji matrisi
    strategy:
      matrix:
        node-version: [18, 20, 22]
        os: [ubuntu-latest, windows-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

Docker Build ve Push

Docker Hub'a Push

hljs yaml
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Docker meta bilgileri
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: kullanici/uygulamam
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=sha,prefix=sha-

      - name: Docker Buildx kurulumu
        uses: docker/setup-buildx-action@v3

      - name: Docker Hub girişi
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - 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
          cache-to: type=gha,mode=max

GitHub Container Registry (GHCR)

hljs yaml
      - name: GHCR girişi
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build ve Push (GHCR)
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:latest

SSH ile Sunucuya Deployment

appleboy/ssh-action Kullanımı

hljs yaml
  deploy:
    needs: docker
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: SSH ile deploy
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.SERVER_PORT }}
          script: |
            cd /root/uygulamam
            git pull origin main
            docker compose pull
            docker compose up -d --remove-orphans
            docker image prune -f
            echo "Deploy tamamlandı: $(date)"

Docker Compose ile Deployment

hljs yaml
      - name: Docker Compose deploy
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            # Yeni image'ı çek
            docker pull ghcr.io/${{ github.repository }}:latest

            # Zero-downtime deploy
            docker compose -f /root/app/docker-compose.yml up -d \
              --no-deps \
              --build \
              --remove-orphans

            # Eski image'ları temizle
            docker image prune -af --filter "until=24h"

            # Health check
            sleep 10
            curl -f http://localhost:3000/health || exit 1

Secrets Yönetimi

GitHub Secrets, hassas bilgileri güvenle saklar:

hljs yaml
# Secrets kullanımı
steps:
  - name: Uygulama yapılandırması
    env:
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
      JWT_SECRET: ${{ secrets.JWT_SECRET }}
      API_KEY: ${{ secrets.API_KEY }}
    run: |
      echo "Yapılandırma yüklendi"
      # Secrets log'a yazdırılmaz, otomatik maskelenir

Gerekli secrets:

  • SERVER_HOST: Sunucu IP adresi
  • SERVER_USER: SSH kullanıcı adı
  • SSH_PRIVATE_KEY: SSH özel anahtarı
  • DOCKERHUB_USERNAME: Docker Hub kullanıcı adı
  • DOCKERHUB_TOKEN: Docker Hub erişim token'ı

Cache Kullanımı

hljs yaml
      - name: Node.js bağımlılıklarını önbelleğe al
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: npm ci (cache'li)
        run: npm ci

      # Docker layer cache
      - name: Build ve Push
        uses: docker/build-push-action@v5
        with:
          cache-from: type=gha
          cache-to: type=gha,mode=max

Matrix Builds

hljs yaml
jobs:
  test:
    strategy:
      fail-fast: false
      matrix:
        node: [18, 20]
        os: [ubuntu-latest, macos-latest]
        include:
          - node: 20
            os: ubuntu-latest
            coverage: true
        exclude:
          - node: 18
            os: macos-latest
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test
      - name: Coverage raporu
        if: matrix.coverage
        run: npm run coverage

Environment Protection Rules

hljs yaml
jobs:
  deploy-production:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com
    steps:
      - name: Production deploy
        run: echo "Production'a deploy ediliyor"

GitHub'da Settings > Environments > production altında:

  • Required reviewers (onay gerektir)
  • Wait timer (bekleme süresi)
  • Deployment branches (sadece main)

Tam CI/CD Pipeline Örneği

hljs yaml
name: Full CI/CD

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm test -- --coverage
      - name: Coverage yükle
        uses: codecov/codecov-action@v4

  build:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    outputs:
      image-tag: ${{ steps.meta.outputs.version }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      - uses: docker/build-push-action@v5
        with:
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    environment:
      name: production
      url: https://example.com
    steps:
      - uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
            docker compose -f /root/app/docker-compose.yml up -d
            docker image prune -f

Sonuç

GitHub Actions ile tam otomatik CI/CD pipeline kurarak kod kalitesini artırabilir, deployment hatalarını azaltabilir ve geliştirme sürecinizi hızlandırabilirsiniz. Secrets yönetimi, cache optimizasyonu ve environment protection rules ile production-grade bir pipeline elde edersiniz.