Skip to content
~/sph.sh

Büyük Ölçekli Mikroservis Mimarisi için Ölçeklenebilir Bir GitHub Actions Platformu Oluşturmak

Organizasyon düzeyinde paylaşımlı bir GitHub Actions platformu kurmak için pratik bir rehber: mimari kararlar, güvenlik yönetişimi, benimseme stratejisi ve bu süreçte yaptığımız en büyük 7 hata.

Özet

CI/CD pipeline'ları düzinelerce repository'de organik olarak büyüdüğünde, ortaya tekrarlayan YAML dosyaları, tutarsız güvenlik uygulamaları ve sürekli gelen destek talepleri çıkar. Bu yazıda, yaklaşık 20 mikroservis çalıştıran büyük bir e-ticaret platformu için birden fazla ekibin kullandığı organizasyon düzeyinde paylaşımlı bir GitHub Actions platformunu nasıl kurduğumuzu anlatıyoruz. Mimari kararları, güvenlik yönetişim modelini, benimseme stratejisini ve ortaya çıkan somut metrikleri ele alıyoruz: build süreleri yaklaşık 45 dakikadan yaklaşık 12 dakikaya düştü, CI ile ilgili destek taleplerinde %70 azalma yaşandı ve altı ay içinde %85'in üzerinde benimseme oranına ulaşıldı. Ayrıca yaptığımız en büyük 7 hatayı da paylaşıyoruz, çünkü bunlar bize doğru giden şeylerden daha fazlasını öğretti.

Giriş

GitHub Actions ile başlamak aldatıcı derecede basittir. Bir YAML dosyası kopyala, birkaç adım ekle ve çalışan bir pipeline'ın olsun. Sorun şu ki bu basitlik ölçeklenmez. farklı mikroservisler için düzinelerce repository'niz olduğunda ve her biri farklı ekipler tarafından kendi build, test ve deploy iş akışlarıyla yönetildiğinde, sessizce mühendislik kapasitesini tüketen bir bakım yükü ortaya çıkar.

Kendimizi tam olarak bu durumda bulduk: ince farklılıklar içeren yüzlerce workflow dosyası, tutarsız güvenlik uygulamaları, büyük farklılıklar gösteren build süreleri ve giderek büyüyen CI ile ilgili destek talepleri. Platform mühendisliği ekibi, platform yetenekleri geliştirmekten çok "GitHub Actions'da X'i nasıl yaparım?" sorularını yanıtlamakla zaman harcıyordu.

Bu yazıda, organizasyon düzeyinde paylaşımlı bir actions platformunu nasıl tasarladığımızı, kurduğumuzu ve devreye aldığımızı belgeliyoruz. Amaç tek bir doğru yaklaşım dayatmak değil, neyin işe yaradığını, neyin yaramadığını ve her kararın arkasındaki ödünleri paylaşmaktır.

Neden Organizasyon Düzeyinde Paylaşımlı Bir Actions Platformuna İhtiyaç Duyduk

Ölçüm yapmaya başlamadan önce bile belirtiler açıktı:

  • Her yerde tekrar: Ortalama workflow dosyası yaklaşık 500 satır YAML'dı ve bunun kabaca %80'i repository'ler arasında aynıydı. Ekipler birbirinden kopyalıyor ve zaman içinde farklılaşıyordu.
  • Tutarsız güvenlik duruşu: Bazı repo'lar action sürümlerini SHA ile sabitlemiş, diğerleri @latest kullanıyordu. Bazıları AWS için OIDC yapılandırmış, diğerleri hâlâ secret olarak saklanan uzun ömürlü erişim anahtarları kullanıyordu.
  • Yavaş build'ler: Ortalama build süresi yaklaşık 45 dakikaydı. Ekipler zaman içinde cache, paralellik veya runner seçimini dikkate almadan adımlar eklemiş.
  • Destek yükü: Platform ekibi haftada yaklaşık 30 CI ile ilgili talep alıyordu; bunlar çoğunlukla yapılandırma, hata ayıklama ve "benim makinemde çalışıyor" sorunlarıyla ilgiliydi.
  • Onboarding sürtünmesi: Yeni projelerin CI/CD kurulumu günler alıyordu çünkü standart bir şablon yoktu ve kurumsal bilgi Slack konuşmalarında yaşıyordu.

Ekiplere CI/CD için "altın yol" sağlayan ama gerektiğinde özelleştirme esnekliğini koruyan bir platforma ihtiyacımız vardı.

Note: "Altın yol" (golden path), iyi desteklenen, fikirli bir varsayılan yapıdır. Ekipler sapabilir, ancak desteklenen yol kullanım senaryolarının %80'inden fazlasını minimum yapılandırmayla karşılamalıdır.

Mimari Kararlar ve Ödünler

Her mimari karar ödünler içeriyordu. Büyük kararları şöyle değerlendirdik.

Composite Action'lar vs. Reusable Workflow'lar vs. Workflow Template'leri

Bu ilk ve en belirleyici karardı. GitHub Actions, CI/CD mantığını paylaşmak için üç mekanizma sunar ve her biri farklı amaçlara hizmet eder:

ÖzellikComposite Action'larReusable Workflow'larWorkflow Template'leri
Soyutlama düzeyiTek adım veya adım grubuTüm job veya workflowYeni repo'lar için başlangıç noktası
Input/OutputTam destekTam destekManuel kopyalama, sonra özelleştirme
Secret erişimiÇağıranın bağlamını devralırAçık secrets: inherit veya adlandırılmışYok (repo'ya kopyalanır)
İç içe kullanımDiğer composite'leri çağırabilirComposite çağırabilir; 10 seviyeye kadar derinlik, toplam 50 çağrıYok
SürümlemeGit tag / SHAGit tag / SHAKopyalama anındaki anlık görüntü
Drift önlemeMerkezi güncellemeMerkezi güncellemeKopyalandıktan sonra yok
Adımlara görünürlükUI'da daraltılmışUI'da ayrı jobTam görünürlük

Kararımız: Her birini kendi amacı doğrultusunda üçünü birden kullanıyoruz:

  • Composite action'lar yeniden kullanılabilir yapı taşları için (Node.js kurulumu ve cache, linting çalıştırma, Docker image'ları oluşturma)
  • Reusable workflow'lar standartlaştırılmış pipeline'lar için (bir Node.js servisi için build-test-deploy, deploy-to-ECS)
  • Workflow template'leri yeni repository'leri mantıklı bir başlangıç yapılandırmasıyla oluşturmak için

Temel içgörü: composite action'lar iyi compose edilir. Reusable workflow'ları composite action'lardan oluşturduk, böylece workflow'un kendisi ince bir orkestrasyon katmanı olurken action'lar implementasyonu içerir.

Paylaşımlı Action'lar için Monorepo vs. Multi-Repo

BoyutMonorepoMulti-Repo
KeşfedilebilirlikTüm action'lar tek yerdeRepository'lere dağılmış
Çapraz değişikliklerTek PR her şeyi güncellerBirden fazla repo'da birden fazla PR
SürümlemePaylaşımlı release döngüsüBağımsız sürümler
CODEOWNERSTek dosya, yol bazlı kurallarRepo bazlı yapılandırma
Action'lar için CIHer şeyi birlikte test etBağımsız test pipeline'ları
Patlama yarıçapıKötü bir release tüm action'ları etkilerİzole hatalar

Kararımız: Monorepo. Keşfedilebilirlik ve çapraz değişiklik avantajları, özellikle katı branch koruması ve otomatik testlerle birleştirildiğinde patlama yarıçapı endişesini aşar. Patlama yarıçapını, bireysel action'ları bağımsız semver tag'leriyle yayınlayarak azaltıyoruz.

Repository Yapısı

shared-actions/├── actions/│   ├── setup-node/│   │   ├── action.yml│   │   └── README.md│   ├── docker-build/│   │   ├── action.yml│   │   └── README.md│   ├── deploy-ecs/│   │   ├── action.yml│   │   └── README.md│   └── security-scan/│       ├── action.yml│       └── README.md├── workflows/│   ├── node-service.yml│   ├── python-service.yml│   └── deploy-production.yml├── tests/│   ├── setup-node.test.yml│   └── docker-build.test.yml├── .github/│   ├── CODEOWNERS│   └── workflows/│       ├── test-actions.yml│       └── release.yml└── docs/    ├── CONTRIBUTING.md    └── MIGRATION.md

Sürümleme Stratejisi

Sürümleme, güvenlik ile geliştirici deneyiminin çarpıştığı noktadır. Katmanlı bir yaklaşım kullanıyoruz:

Politikamız:

  • Harici üçüncü parti action'lar: SHA sabitleme zorunludur. İstisna yoktur. Dependabot güncelleme PR'larını yönetir.
  • Kendi paylaşımlı action'larımız: Production için semver tag'leri, geliştirme ortamları için major tag'ler.
  • Asla @main kullanılmaz: Dahili action'lar için bile, production workflow'larında doğrudan bir branch'e referans verilmesi yasaktır.

Warning: Üçüncü parti action'lar için @main veya @latest kullanmak bir tedarik zinciri saldırı vektörüdür. Ele geçirilmiş bir upstream repository, onu referans alan her workflow'a kötü amaçlı kod enjekte edebilir. Harici action'lar için her zaman SHA ile sabitleyin.

Self-Hosted vs. GitHub-Hosted Runner'lar

BoyutGitHub-HostedSelf-Hosted
BakımSıfırYama, ölçekleme, izleme
Ölçekte maliyetDakika başı faturalandırma artarSabit altyapı maliyeti, yüksek hacimde daha iyi
GüvenlikGeçici, temiz ortamTemizliği yönetmezseniz kalıcı
Ağ erişimiYalnızca genel internetVPC erişimi, özel registry'ler
ÖzelleştirmeMevcut image'larla sınırlıAraçlar üzerinde tam kontrol
Başlangıç süresi~20-40sn (sıcak)~5-10sn (önceden ısıtılmış)
GPU/ÖzelleştirilmişSınırlı seçeneklerTam kontrol

Kararımız: Hibrit. Çoğu iş yükü için GitHub-hosted büyük runner'lar, özel ağ erişimi gerektiren işler (staging veritabanlarına karşı entegrasyon testleri, özel ECS cluster'larına deployment) için VPC'mizdeki self-hosted runner'lar. Eski ortam sorununu önlemek için ECS Fargate üzerinde geçici (ephemeral) self-hosted runner'lar kullanıyoruz.

İmplementasyon Detayları

Composite Action Örneği: Cache ile Node.js Kurulumu

Bu action, repository'ler arasında tekrarlayan yaklaşık 30 satır YAML'ı tek bir adımla değiştirir:

yaml
# actions/setup-node/action.ymlname: "Setup Node.js with Caching"description: "Sets up Node.js, restores npm cache, and installs dependencies"inputs:  node-version:    description: "Node.js version to use"    required: false    default: "20"  working-directory:    description: "Directory containing package.json"    required: false    default: "."
runs:  using: "composite"  steps:    - name: Setup Node.js      uses: actions/setup-node@v4      with:        node-version: ${{ inputs.node-version }}
    - name: Cache npm dependencies      uses: actions/cache@v4      id: npm-cache      with:        path: ~/.npm        key: npm-${{ runner.os }}-${{ hashFiles(format('{0}/package-lock.json', inputs.working-directory)) }}        restore-keys: |          npm-${{ runner.os }}-
    - name: Install dependencies      shell: bash      working-directory: ${{ inputs.working-directory }}      run: npm ci

Reusable Workflow: Node.js Servis Pipeline'ı

Bu, Node.js servisleri için "altın yol" workflow'udur. Birden fazla paylaşımlı action'ı compose eder ve repo başına pipeline YAML'ını yaklaşık 500 satırdan yaklaşık 50 satıra düşürür:

yaml
# workflows/node-service.ymlname: Node.js Service Pipeline
on:  workflow_call:    inputs:      node-version:        type: string        default: "20"      deploy-environment:        type: string        required: true      aws-region:        type: string        default: "eu-central-1"      run-e2e:        type: boolean        default: false    secrets:      AWS_ROLE_ARN:        required: true
permissions:  id-token: write  contents: read
jobs:  build-and-test:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4
      - uses: our-org/shared-actions/actions/setup-node@v2        with:          node-version: ${{ inputs.node-version }}
      - name: Lint        run: npm run lint
      - name: Unit tests        run: npm run test:unit -- --coverage
      - name: Build        run: npm run build
      - uses: our-org/shared-actions/actions/security-scan@v2
  deploy:    needs: build-and-test    runs-on: ubuntu-latest    environment: ${{ inputs.deploy-environment }}    steps:      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4        with:          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}          aws-region: ${{ inputs.aws-region }}
      - uses: our-org/shared-actions/actions/deploy-ecs@v2        with:          environment: ${{ inputs.deploy-environment }}

Bir Consumer Repository Nasıl Görünür

Bu, tipik bir Node.js servisi için tüm CI/CD yapılandırmasıdır. Başladığımız 500 satırlık dosyalarla karşılaştırın:

yaml
# .github/workflows/ci.yml (in consumer repo)name: CI/CD
on:  push:    branches: [main]  pull_request:    branches: [main]
jobs:  pipeline:    uses: our-org/shared-actions/.github/workflows/node-service.yml@v2    with:      node-version: "20"      deploy-environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}      run-e2e: ${{ github.ref == 'refs/heads/main' }}    secrets:      AWS_ROLE_ARN: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}

Bu yaklaşık 20 satır YAML'dır. Ekip, build cache'i, güvenlik taraması, OIDC tabanlı AWS kimlik doğrulaması ve standartlaştırılmış deploy sürecini hiçbirini yapılandırmadan elde eder.

Otomatik Release Pipeline'ı

Paylaşımlı actions monorepo'sunda, değişiklikler main'e merge edildiğinde bireysel action'lar için semver tag'leri oluşturan bir release workflow'u kullanıyoruz:

yaml
# .github/workflows/release.ymlname: Release Actions
on:  push:    branches: [main]    paths:      - "actions/**"      - "workflows/**"
jobs:  detect-changes:    runs-on: ubuntu-latest    outputs:      changed-actions: ${{ steps.changes.outputs.actions }}    steps:      - uses: actions/checkout@v4        with:          fetch-depth: 0
      - id: changes        run: |          changed=$(git diff --name-only HEAD~1 HEAD | grep '^actions/' | cut -d'/' -f2 | sort -u | jq -R . | jq -s .)          echo "actions=$changed" >> "$GITHUB_OUTPUT"
  release:    needs: detect-changes    if: needs.detect-changes.outputs.changed-actions != '[]'    runs-on: ubuntu-latest    strategy:      matrix:        action: ${{ fromJson(needs.detect-changes.outputs.changed-actions) }}    steps:      - uses: actions/checkout@v4
      - name: Determine version bump        id: version        run: |          # Read version from action.yml metadata or use conventional commits          echo "version=v2.1.3" >> "$GITHUB_OUTPUT"
      - name: Create release tag        run: |          git tag "${{ matrix.action }}/${{ steps.version.outputs.version }}"          git push origin "${{ matrix.action }}/${{ steps.version.outputs.version }}"

Güvenlik ve Yönetişim Katmanı

Ölçekte güvenlik isteğe bağlı değildir. Bireysel ekiplerin düşünmesine gerek kalmayacak şekilde birden fazla katman aracılığıyla uyguluyoruz.

AWS Kimlik Doğrulama için OIDC

GitHub secret'ları olarak saklanan uzun ömürlü AWS kimlik bilgileri bir sorumluluktur. Hepsini belirli repository'lere ve ortamlara kapsamlandırılmış OIDC federasyonuyla değiştirdik:

yaml
# IAM trust policy (Terraform){  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Principal": {        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"      },      "Action": "sts:AssumeRoleWithWebIdentity",      "Condition": {        "StringEquals": {          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"        },        "StringLike": {          "token.actions.githubusercontent.com:sub": "repo:our-org/service-*:environment:production"        }      }    }  ]}

sub claim koşulu kritik öneme sahiptir. Hangi repository'lerin ve ortamların bu rolü üstlenebileceğini kısıtlar. our-org/random-fork adlı bir repository, workflow yapılandırmasını bir şekilde elde etmiş olsa bile production rollerini üstlenemez.

Tedarik Zinciri Güvenliği

Çok katmanlı bir tedarik zinciri güvenlik stratejisi uyguladık:

Temel yapılandırmalar:

  • StepSecurity Harden Runner: Workflow yürütmesi sırasında giden ağ çağrılarını izler. Ele geçirilmiş bir action, secret'ları bilinmeyen bir endpoint'e sızdırmaya çalışırsa işaretlenir.
  • Action'lar için Dependabot: Sabitlenmiş action SHA'larının daha yeni sürümleri olduğunda otomatik PR'lar oluşturur. Bu, güvenlikten ödün vermeden güncel kalmamızı sağlar.
  • OpenSSF Scorecard: Kendi uygulamalarımızdaki güvenlik zayıflıklarını ortaya çıkarmak için paylaşımlı actions repo'sunda haftalık çalışır.

CODEOWNERS ve Branch Koruması

Paylaşımlı actions repository'sinde katı yönetişim kuralları var:

# .github/CODEOWNERS# Platform team owns everything by default* @our-org/platform-engineering
# Security team must review security-related actionsactions/security-scan/ @our-org/security-team @our-org/platform-engineeringworkflows/deploy-*.yml @our-org/security-team @our-org/platform-engineering
# Individual teams own their contributed actionsactions/mobile-build/ @our-org/mobile-team @our-org/platform-engineering

Branch koruma kuralları:

  • 2 onaylayıcı review gerektirir (en az 1'i platform ekibinden)
  • Durum kontrollerinin başarılı olması gerekir (tüm action testleri geçmeli)
  • İmzalı commit'ler gerektirir
  • main'e force push veya silme yasaktır
  • Yeni push'larda eski review'ları geçersiz kılar

Minimal Token İzinleri

Her workflow en kısıtlayıcı izinlerle başlar ve ihtiyaç duyduğu şeyleri açıkça tanımlar:

yaml
# Default: no permissionspermissions: {}
# Then grant only what's needed per jobjobs:  deploy:    permissions:      id-token: write   # For OIDC      contents: read     # For checkout

Tip: Workflow düzeyinde permissions: {} ayarlayın ve ardından her job'ın sadece ihtiyaç duyduğunu verin. Bu, en az ayrıcalık ilkesini takip eder ve güvenlik duruşunu bir bakışta denetlenebilir kılar.

Benimseme ve Ölçüm Stratejisi

Platform kurmak kolay kısımdır. Büyük bir mikroservis organizasyonundaki birden fazla ekibin onu kullanmasını sağlamak asıl zorluktur.

Inner Source Katkı Modeli

Yukarıdan aşağıya bir zorunluluk yerine açıkça bir inner source modeli seçtik. Platform ekibi temel action'ları yönetir, ancak herhangi bir mühendis katkıda bulunabilir:

Katkı süreci:

  1. RFC issue: Sorunu ve önerilen action'ı tanımlayın. Platform ekibi kapsam, adlandırma ve mevcut örtüşmeler hakkında geri bildirim verir.
  2. İmplementasyon: Katkıda bulunan, action, testler ve dokümantasyonla birlikte bir PR açar.
  3. Review: Platform ekibi tutarlılık, güvenlik ve composability açısından inceler. CODEOWNERS doğru kişilerin review yapmasını sağlar.
  4. Release: Merge edilen PR'lar uygun semver tag'leriyle otomatik release'leri tetikler.
  5. Duyuru: Yeni action'lar mühendislik Slack kanalında bir kullanım örneğiyle duyurulur.

Bu model benimseme için kritikti. Mobil ekip bir mobile-build action'ı katkıda bulunduğunda, ekip arkadaşları onu platform ekibinin kurmuş olmasından çok daha kolay benimsedi.

Geçiş Planı

Yapılandırılmış bir geçiş rehberi oluşturduk. Önemli olan, ekipleri her şeyi bir kerede geçirmeye zorlamamaktı:

  1. Faz 1: Kimlik bilgisi yönetimini OIDC ile değiştirme (güvenlik kazanımı, workflow değişikliği gerektirmez)
  2. Faz 2: setup-node veya setup-python composite action'larını benimseme (kolay değişim, anında cache avantajları)
  3. Faz 3: Standart servis pipeline'ları için reusable workflow'lara geçiş
  4. Faz 4: Güvenlik taraması için repository ruleset'leri benimseme

Her faz bağımsız olarak değerliydi, bu da ekiplerin kademeli olarak geçiş yapabilmesi anlamına geliyordu.

DORA Metrikleri Dashboard'u

Temel DORA metriklerini ve platforma özgü KPI'ları izliyoruz:

MetrikPlatform ÖncesiPlatform SonrasıDeğişim
Deployment SıklığıEkip başına haftada ~2Ekip başına haftada ~8+%300
Değişiklik İçin Bekleme Süresi~4 gün~1,5 gün-%62
Değişiklik Hata Oranı~%18~%8-%56
Başarısız Dağıtım Kurtarma Süresi~3 saat~45 dakika-%75
Ortalama Build Süresi~45 dakika~12 dakika-%73
Haftalık CI Destek Talepleri~30~9-%70
Repo Başına Pipeline YAML~500 satır~50 satır-%90

Note: Bu iyileştirmeler yalnızca paylaşımlı actions platformundan kaynaklanmadı. Cache, runner optimizasyonu ve paralellik de önemli katkılarda bulundu. Platform, tüm bu optimizasyonları tutarlı bir şekilde benimsemeyi kolaylaştırdı.

Öğrenilen Dersler ve En Büyük 7 Hata

Bunlar bize en çok zaman kaybettiren hatalardır. Her biri, sıfırdan başlasaydık farklı yapacağımız şeylerdir.

Hata 1: Geri Bildirim Almadan Çok Fazla Şey İnşa Etmek

Herhangi bir ekip kullanmadan önce kapsamlı bir paylaşımlı action seti oluşturmak için haftalar harcadık. Sonunda teslim ettiğimizde, soyutlamalar ekiplerin projelerini gerçekte nasıl yapılandırdığıyla eşleşmiyordu. Gerçek kullanım yanlış varsayımları ortaya çıkardıktan sonra birkaç action'ı yeniden yazmak zorunda kaldık.

Bunun yerine işe yarayan: İlk olarak en küçük faydalı action'ı teslim edin. Sadece setup-node ile başlamalı, 5 ekibin kullanmasını sağlamalı ve sonra genişlemeliydik.

Hata 2: Aşırı Soyut Reusable Workflow'lar

İlk reusable workflow'larımız, input'lar aracılığıyla olası her yapılandırmayı karşılamaya çalıştı. node-service.yml workflow'unun 23 input'u vardı. Ekipler bunu kendi YAML'larını yazmaktan daha zor buldu.

Bunun yerine işe yarayan: Daha az input, daha fikirli varsayılanlar. Mevcut workflow'larımız 4-6 input'a sahip. Bir ekip önemli ölçüde farklı davranışa ihtiyaç duyarsa, workflow'u parametrize etmek yerine action'larımızdan compose eder.

Hata 3: Workflow Hata Ayıklama Deneyimini Göz Ardı Etmek

Bir reusable workflow başarısız olduğunda, hata çağıran workflow'un loglarında görünür, ancak gerçek adımlar reusable workflow'un tanımındadır. Bu, özellikle ara adımları net göremediklerinde hata ayıklama sırasında ekiplerin kafasını karıştırdı.

Bunun yerine işe yarayan: Composite action'lara açık adım adlarıyla ayrıntılı loglama ekleyin. Daraltılabilir bölümler oluşturmak için ::group:: ve ::endgroup:: log komutlarını kullanın. Hata ayıklamanın tam olarak hangi sürümün çalıştığını tanımlayabilmesi için paylaşımlı action sürümünü log çıktısına dahil edin.

Hata 4: Breaking Change Politikası Olmaması

Standart olmayan node_modules konumlarına sahip repository'leri bozacağını fark etmeden cache stratejisini değiştiren bir setup-node v2'si yayınladık. Bu, 15 repo'da aynı anda hatalara neden oldu.

Bunun yerine işe yarayan: Belgelenmiş bir breaking change politikasıyla semantik sürümleme. Major sürüm artışları bir geçiş rehberi ve iki haftalık bir kullanımdan kaldırma bildirimi gerektirir. Artık yayınlamadan önce yeni action sürümlerini consumer repository'lerin bir örneğine karşı test eden otomatik bir uyumluluk kontrolü çalıştırıyoruz.

Hata 5: Runner Maliyetlerini Küçümsemek

Başlangıçta hız için tüm job'ları varsayılan olarak ubuntu-latest-16core runner'lara atadık. GitHub Actions faturası beklenenden çok daha hızlı büyüdü. Her job büyük runner'lardan fayda görmez; bağımlılık yüklemesi genellikle CPU'ya değil ağa bağlıdır.

Bunun yerine işe yarayan: Standart runner'ları varsayılan yapın ve belgelenmiş gerekçeyle job bazında büyük runner'lara geçin. Yeni action'ları, büyük runner'ların build sürelerini gerçekten iyileştirip iyileştirmediğini belirlemek için önce profilliyoruz.

Hata 6: Güvenliği Görünmez Yerine Sıkıcı Yapmak

İlk güvenlik taraması implementasyonumuz her pipeline'a 8 dakika ekledi ve yanlış pozitiflerle dolu gürültülü raporlar üretti. Ekipler güvenlik adımlarını atlamak için if: false koşulları eklemeye başladı, bu da tüm amacı boşa çıkardı.

Bunun yerine işe yarayan: Güvenlik taraması hızlı olmalı ve düşük yanlış pozitif oranına sahip olmalıdır. Artımlı taramaya geçtik (PR'larda yalnızca değişen dosyaları tara, main'de tam tarama), sürekli yanlış pozitif üreten kural setlerini ayarladık ve tarama süresini 90 saniyenin altına düşürdük. Bir darboğaz olmaktan çıktığında benimseme yaklaşık %40'tan %95'e çıktı.

Hata 7: Eski Kalıplar için Kullanımdan Kaldırma Yolu Olmaması

Paylaşımlı platformu yayınladığımızda, repository'lerden eski workflow dosyalarını kaldırmak için bir planımız yoktu. Bazı repo'lar aylarca hem eski hem yeni pipeline'ları çalıştırdı, işlem gücü israf etti ve hangi sonuçlara güvenileceği konusunda kafa karışıklığı yarattı.

Bunun yerine işe yarayan: Eski kalıpları algılayabilen, geçiş PR'ları oluşturabilen ve organizasyon genelinde geçiş ilerlemesini izleyebilen bir migration CLI aracı oluşturun. Yeni pipeline'ın çalıştığı onaylandıktan sonra kullanımdan kaldırılmış workflow dosyalarını kaldırmak için otomatik PR'lar açan basit bir script oluşturduk.

Sonuçlar, Metrikler ve Gelecek Yol Haritası

Ölçülen Sonuçlar

Altı aylık kademeli yaygınlaştırma sonrasında:

  • %85 benimseme oranı: 40 repository'den 34'ü paylaşımlı action'lara geçti. Kalan 6'sının özel pipeline'lar için meşru nedenleri var (özelleştirilmiş donanım, standart dışı build sistemleri).
  • Build süresi azalması: Ortalama, standartlaştırılmış cache, paralelleştirilmiş test yürütme ve doğru boyutlandırılmış runner'lar sayesinde yaklaşık 45 dakikadan yaklaşık 12 dakikaya düştü.
  • CI destek taleplerinde %70 azalma: Haftada yaklaşık 30'dan yaklaşık 9'a. Kalan talepler çoğunlukla "cache'i nasıl yapılandırırım" yerine gerçekten yeni gereksinimlerle ilgili.
  • Pipeline YAML azalması: Repository başına yaklaşık 500 satırdan yaklaşık 50 satıra. Bu, ekiplerin en doğrudan hissettikleri metriktir çünkü bilişsel yüklerini azaltır.
  • Güvenlik duruşu: Aktif repository'lerin %100'ü AWS kimlik doğrulaması için OIDC kullanıyor. GitHub secret'larında sıfır uzun ömürlü AWS kimlik bilgisi.

Mimari Genel Bakış

Gelecek Yol Haritası

Üç alana yatırım yapıyoruz:

  1. Dinamik pipeline oluşturma: Statik YAML yerine, repository metadata'sına (dil, deployment hedefi, uyumluluk gereksinimleri) dayalı workflow yapılandırmaları üretmek. Bu, repo başına yapılandırmayı sıfıra yakın düzeye indirebilir.
  2. PR başına geçici ortam: Her pull request için bir preview ortamı oluşturmak ve merge sonrası otomatik temizlik yapmak üzere paylaşımlı deploy action'ını kullanmak.
  3. Maliyet atıflandırma: GitHub Actions dakikalarını ekip, servis ve workflow türüne göre etiketleyerek mühendislik yöneticilerine CI/CD harcamaları üzerinde görünürlük sağlamak ve optimizasyon fırsatlarını belirlemeye yardımcı olmak.

Bu Yolculuğa Başlamak

Benzer bir çaba düşünen ekipler için, bizim için işe yarayan sıralama şöyle:

  1. Tek bir yüksek değerli action ile başlayın (cache veya güvenlik taraması) ve 3-5 ekibin kullanmasını sağlayın.
  2. Öncesi ve sonrasını ölçün: build süreleri, destek talepleri, benimseme oranı. Rakamlar organizasyonel desteği sağlar.
  3. Katkı modeline erken yatırım yapın. Yalnızca platform ekibi paylaşımlı action'ları değiştirebilirse, bir darboğaz yaratmış olursunuz.
  4. Güvenlik görünmez olmalı, engel değil. Ekipler güvenlik kontrollerinizi atlatıyorsa, kontroller başarısızdır.
  5. Kullanımdan kaldırmayı ilk günden planlayın. Her v1 sonunda v2 olacaktır ve oraya ulaşmak için bir yola ihtiyacınız var.

Paylaşımlı actions platformu, platform mühendisliği ekibimizin yaptığı en yüksek kaldıraç etkisine sahip yatırımlardan biri oldu. Başlangıç çabası önemliydi, ancak geliştirici üretkenliği, güvenlik tutarlılığı ve operasyonel güvenilirlik açısından bileşik getiriler bunu fazlasıyla haklı çıkardı.

Kaynaklar

İlgili Yazılar