Nasıl Doğrulanır?
Nasıl Doğrulanır?
GitHub Actions başarılı olarak işaretleniyor ✅ Başarılı. Ancak sunucu buna katılmadı.
Bir CI/CD sorunuyla karşılaştık: main dalına kod gönderdikten sonra, GitHub dağıtımı başarılı olarak işaretledi ama sunucuyu kontrol ettiğimizde eski kodun çalıştığını gördük. Hata yok. Uyarı yok. Sadece üretimde eski kod çalışıyordu.
Bu makale, kök nedenin yanı sıra uyguladığımız iki aşamalı düzeltmeyi açıklıyor: kilit tespiti ve commit SHA doğrulaması.
Kurulum
Kurulum
Dağıtım mimarimiz, webhook tabanlı bir yaklaşım kullanmaktadır (SSH yok):
GitHub Actions → HTTP POST → deploy.php sunucusunda → deploy.sh çalıştırılır
Neden SSH yerine webhooks? Hosting sağlayıcımız (Hypernode) SSH erişimi için IP beyaz listeleme yapıyor. GitHub Actions, engellenen dinamik Azure IP’leri üzerinde çalışıyor. Port 443 (HTTPS) gibi bir kısıtlama yok.
Akış şöyle görünmektedir:
- name: Sunucuda dağıtımı başlat
run: |
response=$(curl -s -w "\n%{http_code}" \
-X POST https://www.yoursite.nl/deploy.php \
-H "X-Deploy-Token: ${{ secrets.DEPLOY_WEBHOOK_TOKEN }}" \
--max-time 300)
code=$(echo "$response" | tail -n 1)
if [ "$code" != "200" ]; then
echo "❌ Dağıtım başarısız oldu (HTTP $code)"
exit 1
fi
echo "✅ Dağıtım başarılı"
Ve deploy.php, deploy.sh’yi senkron olarak çalıştırır:
exec("bash {$script} 2>&1", $output, $exit);
echo implode("\n", $output) . "\n";
http_response_code($exit === 0 ? 200 : 500);
Güçlü görünüyor, değil mi? exec() çağrısı engelleyicidir — PHP, deploy.sh’nin bitmesini bekler. Yani GitHub her zaman doğru bir sonuç almalıdır.
Çoğunlukla öyle. Ama sessiz bir şekilde yalan söyleyen bir durum var.
Kök Neden: Sessiz Kilit Atlamaları
deploy.sh, eşzamanlı dağıtımları önlemek için bir kilit dosyası kullanır:
LOCK_FILE="/tmp/mysite-deploy.lock"
if [ -f "$LOCK_FILE" ]; then
log "HATA: Dağıtım zaten devam ediyor. İptal ediliyor."
exit 1
fi
touch "$LOCK_FILE"
trap "rm -f $LOCK_FILE" EXIT
İkinci bir gönderim, dağıtım devam ederken gerçekleşirse:
- İkinci dağıtım deploy.php’yi vurur
- deploy.sh kilit dosyasını bulur → exit 1
- deploy.php HTTP 500 döner
- GitHub Actions 500’ü görür → ❌ başarısız olarak işaretler
O kısım aslında her şeyin düzgün işlediği anlamına geliyor. Ancak burada ince bir sorun var: ilk dağıtım yol ortasında başarısız olabilir (git fetch’te ağ kesintisi, OOM kill, zaman aşımı) ve geride kilit dosyasını bırakarak diğer tüm dağıtımlar sessiz bir şekilde atlanır. deploy.sh çıkış 1 yapar, deploy.php 500 döner ve iş akışınız yanıtı nasıl ele alırsa alsın, yanıltıcı bir sonuç görebilirsiniz.
Dahası: dağıtımlar başarılı olsa bile, aslında hangi commit’in geldiğine dair bir kanıt yoktu. Manuel olarak SSH ile girip dosya zaman damgalarını kontrol etmek ya da bilinen bir dizgiyi grep’lemek zorunda kalıyorduk. Bu sürdürülebilir değil.
Düzeltme: İki Parça
1. Parça — Kilitli olduğunda 423 döndür
deploy.sh, sessiz bir şekilde kilidi yönettikten ziyade, önce deploy.php’de tespit et ve anlamlı bir HTTP durumu döndür:
$lockFile = '/tmp/mysite-deploy.lock';
if (file_exists($lockFile)) {
http_response_code(423);
echo "KİLİTLİ: Dağıtım şu anda devam ediyor. Lütfen kısa süre sonra tekrar deneyin.\n";
exit;
}
exec("bash {$script} 2>&1", $output, $exit);
echo implode("\n", $output) . "\n";
http_response_code($exit === 0 ? 200 : 500);
HTTP 423 Locked burada anlamsal olarak doğrudur — “kaynağın şu anda kilitli olduğu” anlamına gelen standart bir durum kodu.
Akışı güncelleyin ve 423’ü belirgin bir hata olarak değerlendirin:
if ["$code" = "423"]; then
echo "⚠️ Dağıtım kilitli — önceki dağıtım hala çalışıyor"
exit 1
fi
if ["$code" != "200"]; then
echo "❌ Dağıtım başarısız oldu (HTTP $code)"
exit 1
fi
Artık CI’de genel bir hata veya yanlış başarı yerine net bir sinyal alıyorsunuz.
2. Parça — Bir Sürüm Dosyası Yazın, SHA’yı Doğrulayın
deploy.sh’de, tüm adımlar başarılı bir şekilde tamamlandıktan sonra, dağıtılan commit SHA’sını halka açık bir dosyaya yazın:
# git reset --hard sonrası SHA'yı yakala
DEPLOYED_COMMIT=$(git rev-parse HEAD)
log "✓ Kod güncellendi (commit: $DEPLOYED_COMMIT)"
# ... composer install, yarn build, artisan komutları ...
# En son, sürüm dosyasını yaz
echo "$DEPLOYED_COMMIT $(date -u +%Y-%m-%dT%H:%M:%SZ)" > public/version.txt
log "✓ Sürüm dosyası yazıldı: $DEPLOYED_COMMIT"
Bu dosya, git clean’den (bu onu siler) sonra yazılır ve deploy.sh çıkmadan hemen önce, böylece deploy.php 200 dönerken version.txt zaten disk üzerindedir ve doğru SHA’yı içerir.
Herhangi bir yanlışlıkla commit edilmesini engellemek için .gitignore’a ekleyin: public/version.txt
3. Parça — GitHub Actions’da Doğrulama Ekleyin
Webhook tetikleme işleminden sonra bir doğrulama adımı ekleyin:
- name: Sunucuda dağıtımı tetikle
run: |
# ... mevcut webhook çağrısı ...
- name: Dağıtımın gerçekleştiğini doğrula
run: |
EXPECTED="${{ github.sha }}"
echo "Beklenen SHA: $EXPECTED"
for i in $(seq 1 20); do
sleep 15
DEPLOYED=$(curl -sf "https://www.yoursite.nl/version.txt" 2>/dev/null | awk '{print $1}')
echo "Deneme $i/20: sunucu=${DEPLOYED:-yok}"
if [ "$DEPLOYED" = "$EXPECTED" ]; then
echo "✅ Sunucuda dağıtım onaylandı: $DEPLOYED"
exit 0
fi
done
echo "❌ Dağıtım doğrulaması 5 dakika sonra BAŞARISIZ oldu"
echo "Beklenen: $EXPECTED"
echo "Aldı: ${DEPLOYED:-sunucudan yanıt yok}"
exit 1
Bu, version.txt’i her 15 saniyede bir 5 dakika boyunca sorgular. Deploy.php senkron exec() kullandığı için, bu adım çalıştığında dağıtım çoktan tamamlanmış olacaktır, bu nedenle ilk sorgu (15 saniye içinde) hemen hemen her zaman anında eşleşir.
Sonuçlar
Düzeltmeden sonra GitHub Actions günlükleri şöyle görünmektedir:
Run EXPECTED="6f250fe1a2b9bb11ea826325a8a486b25279dfb1"
Waiting for deploy to complete on server...
Beklenen SHA: 6f250fe1a2b9bb11ea826325a8a486b25279dfb1
Deneme 1/20: sunucu=6f250fe1a2b9bb11ea826325a8a486b25279dfb1
✅ Sunucuda dağıtım onaylandı: 6f250fe1a2b9bb11ea826325a8a486b25279dfb1
İlk denemede onaylandı, beklemeye gerek yok.
Herhangi bir zaman manuel olarak da doğrulama yapabilirsiniz:
curl -s https://www.yoursite.nl/version.txt
# 6f250fe1a2b9bb11ea826325a8a486b25279dfb1 2026-05-28T03:41:30Z
Neden Sunucuda sadece git log kullanmıyorsunuz?
SSH ile girip git log -1 çalıştırabilirsiniz — ama CI’dan SSH erişimi gerektirir (bizde engellenmiştir), ayrı bir izleme görevi veya manuel kontroller gerektirir. version.txt yaklaşımı, kimlik bilgileri gerektirmeden, herhangi bir yerden, hatta tarayıcıdan bile düz HTTPS üzerinden çalışıyor.
Bu ayrıca endişeleri ayırır: GitHub Actions sonucu doğrular, süreci değil. Deploy.sh’nin iç yapısı değişse bile, doğrulama sözleşmesi aynı kalır “sunucu doğru SHA’yı bildiriyor mu?”
Özet
┌──────────────────────────────────────────────────┬───────────────────────────────────────┐
│ Problem │ Çözüm │
├──────────────────────────────────────────────────┼───────────────────────────────────────┤
│ Dağıtım kilitliyken sinyal yok │ deploy.php HTTP 423 döner │
├──────────────────────────────────────────────────┼───────────────────────────────────────┤
│ Hangi commit'in geldiğine dair kanıt yok │ deploy.sh halka açık/version.txt yazar│
├──────────────────────────────────────────────────┼───────────────────────────────────────┤
│ GitHub, sunucu doğrulaması olmadan başarı gösteriyor │ GitHub Actions SHA'yı sorgular ve doğrular │
└──────────────────────────────────────────────────┴───────────────────────────────────────┘
Üç küçük değişim. Sıfır yeni bağımlılık. Düz HTTP üzerinden statik bir dosya sunabilen herhangi bir yığınla çalışır.
Kaynak: Orijinal Makale


