Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
GitHub CLI ile Terminalden GitHub: gh pr, gh issue, gh run, gh api ve Extension'lar
GitHub CLI (gh) bir Git aracı değil, GitHub API'sine konuşan bir istemci; doğru scope'lu bir token'la pull request, issue, CI run'ları ve release'ler terminalden yönetilir. gh pr, gh issue, gh run, gh api, alias ve extension'ları, Bookstore'da PR'dan auto-merge'e iki satırlık akışı ve GH_HOST ile scope tuzaklarını anlatıyoruz.
Geçmişte Arama: git grep, git log -S/-G/-L, blame -w -C, ignoreRevsFile ve "Bu Satır Ne Zaman, Neden Değişti?"
Bir satırı kimin, ne zaman, neden değiştirdiğini bulmak için blame'in ilk cevabı yetmez: git log -S metnin ortaya çıktığı commit'i, -G o satırların her değişimini, -L tek bir method'un geçmişini verir. Bookstore'daki kurumsal indirim hatasını git grep, pickaxe, blame -w -C ve .git-blame-ignore-revs ile Git 2.56'da izliyoruz.
git config Derinlemesine: includeIf ile İş/Kişisel Kimlik, İki GitHub Hesabı, url.insteadOf ve Ekip için Önerilen Ayarlar
includeIf "gitdir:~/work/" ile iş kimliği yalnız o klasördeki repo'lara uygulanır; sondaki / unutulursa koşul sessizce tutmaz. hasconfig ile remote URL'ine göre kimlik, SSH host alias'ı ve url.insteadOf ile iki GitHub hesabı, credential helper'da useHttpPath ve ekip için önerilen ayarları Git 2.56 ile deniyoruz.
Büyük Repo'larla Çalışmak: Git LFS, Partial Clone, Sparse Checkout, Shallow Clone ve Geçmişten Büyük Dosya Silmek
Silinmiş bir dosya bile geçmişte durduğu için her clone'u şişirir; çözüm clone'da partial clone, sparse checkout ve shallow clone ile yükü atlamak, kalıcı olarak da git filter-repo ile geçmişi temizlemektir. Bookstore'un kitap kapaklarını Git LFS'e taşıyor, GitHub LFS kotalarını, CI'da fetch-depth'i ve scalar'ı Git 2.56 ile deniyoruz.
Git Submodule ve Subtree: Başka Bir Repo'yu Projeye Bağlamak ve Monorepo mu Polyrepo mu?
Submodule, üst repo'da dosyaları değil yalnız bir commit hash'ini (gitlink) saklar; bu yüzden clone'da --recurse-submodules, güncellemede pointer'ı commit'lemek gerekir. Bookstore'un ortak sözleşme repo'sunu submodule ve subtree ile bağlıyor, CI ayarını, paketle paylaşmayı ve monorepo kararını karşılaştırıyoruz.
Script'i Test Etmek ve CI'da Çalıştırmak: Pester 6, PSScriptAnalyzer, Cross-Platform ve 5.1'den 7.x'e Taşımak
GitHub Actions'ta shell: pwsh adımı yalnız $ErrorActionPreference = 'stop' ekler; ortadaki dotnet test kırılsa da son native komut 0 dönerse adım yeşil kalır, bu yüzden run bloğunu tek bir script çağrısı yap. Bookstore.Ops için Pester 6 testleri ve mock'lar, PSScriptAnalyzer kuralları, Windows ve Ubuntu matrix'i, cross-platform tuzaklar, 5.1'den 7.x'e ve 7.6'dan 7.7'ye geçişteki farklar.
Uzak Sunucu Yönetimi: SSH Tabanlı Remoting, Invoke-Command, Session'lar ve Credential'ı Script'e Gömmemek
PowerShell remoting'de Invoke-Command'dan dönen object'ler serialize edilmiş kopyalardır: property'ler gelir, method'lar gelmez; uzaktaki işi script bloğunun içinde yap. SSH tabanlı remoting, $using:, session'lar, ikinci hop, SecretManagement ile vault'tan secret okumak ve Bookstore.Api'yi iki sunucuya sırayla deploy eden, ilk hatada duran bir rollout script'i.
Gerçek İşler: Dosya Sistemi, REST API, JSON/CSV, Scheduled Task, Windows Service, IIS ve Windows'ta Network Teşhisi
ConvertTo-Json varsayılan olarak yalnız 2 seviye derine iner; API'ye gönderilen iç içe gövde sessizce "System.Collections.Hashtable" string'ine dönüşür, bu yüzden her gövdeye -Depth ver. Bearer token, -MaximumRetryCount'un 401'de bile POST'u tekrarlaması, $PSScriptRoot ve CSV encoding, Windows Service, scheduled task, IIS ve network komutları, sonunda Bookstore.Api için yedek alan ve geri dönebilen bir deploy script'i.
Function'dan Module'e: Advanced Function, [CmdletBinding()], Parametre Doğrulama, Pipeline Input ve -WhatIf
PowerShell'de function'ın sonucu return değil, success stream'e düşen her şeydir; advanced function ([CmdletBinding()]) bunu, parametre doğrulamayı, pipeline input'u ve -WhatIf/-Confirm'ü cmdlet gibi yönetmeyi sağlar. Bookstore.Ops module'ünü manifest'iyle yazıyor, module'e geçmeyen preference'ları ve CI'da ShouldProcess tuzağını gösteriyor, PSResourceGet ile yerel bir repository'den kuruyoruz.
Error Handling: Terminating ve Non-Terminating Hatalar, $ErrorActionPreference, try/catch ve Native Komutların Exit Code'u
PowerShell'de $ErrorActionPreference = 'Stop' yalnız PowerShell hatalarını durdurur; dotnet test gibi native komutun başarısız exit code'u için $PSNativeCommandUseErrorActionPreference = $true da gerekir, yoksa testler kırılsa bile publish çalışır ve script 0 ile çıkar. İki hata türünü, try/catch/finally ve trap'i, Write-Error ile throw farkını, stderr ve 2>&1 davranışını, Set-StrictMode'u, set -euo pipefail karşılıklarını ve Bookstore için ilk hatada duran bir build script'ini gösteriyoruz.
Koşullar, Döngüler ve Pipeline'ı Script'te Kullanmak: switch, foreach, Where-Object, ForEach-Object ve -Parallel
PowerShell'de foreach statement bellekteki koleksiyonda en hızlısıdır, dosyadan akan veride ise pipeline erken durabildiği için çok daha az iş yapar; ForEach-Object içindeki break ise script'in kalanını atlar. Karşılaştırma operatörlerini, switch -Regex ile log okumayı, begin/process/end bloklarını ve ForEach-Object -Parallel'i Bookstore'un 200 kitap kapağını kontrol eden bir script'le, $using:, race condition ve Format-Table tuzaklarıyla birlikte gösteriyoruz.
Variable'lar, Tipler ve Koleksiyonlar: [type] Cast, Array, Hashtable, PSCustomObject, Splatting ve String'ler
PowerShell'de karşılaştırmanın sonucu soldaki değerin tipine bağlıdır ve Import-Csv her sütunu string okur; bu yüzden veriyi en başta gerçek tiplere çevirmek gerekir. Bookstore'un kitap CSV'sinden yayınevi raporu çıkarırken $null'ı sola yazma kuralını, array ve +=, List, hashtable, PSCustomObject, splatting, string'ler, Türkçe culture'da sayı ve tarih tuzaklarını ve PowerShell 7.7'de [decimal] cast'inin .NET 11 yüzünden farklı sonuç vermesini gösteriyoruz.