Tüm kaynak kodları ve belgeleri (durum.md + plan.md) detaylıca inceledim. İşte projenin kısa bir fotoğrafı:
- Stage-bazlı mimari — Kurulum 8 bağımsız aşamaya bölünmüş, bu bakım kolaylığı sağlıyor
- Modern arayüz — Glassmorphism, gradient'ler, animasyonlar ile etkileyici UI
- Gerçek sistem araç entegrasyonu —
lsblk,sgdisk,rsync,chroot,dracut,grub2kullanımı - Log dışa aktarma — Kurulum oturumunu
.logve.summary.jsonolarak kaydetme - 3 dil desteği — Türkçe, İngilizce, İspanyolca çevirileri mevcut
| # | Sorun | Etki |
|---|---|---|
| 1 | Test altyapısı yok | Herhangi bir değişikliğin etkisi ölçülemiyor |
| 2 | Boot zinciri eksik | Kurulum sonrası sistem açılmıyor |
| 3 | useradd çağrısı yok |
Kullanıcı oluşturulmadan parola atanıyor |
| 4 | Root parolası root:root |
Ciddi güvenlik açığı |
| 5 | Manuel bölümleme hayali | UI'da plan yapılıyor ama diske uygulanmıyor |
| 6 | BLS girişleri üretilmiyor | Fedora 43'te grub2-mkconfig tek başına yetmeyebilir |
| 7 | /etc/kernel/cmdline yok |
Boot parametreleri eksik |
| 8 | Reboot butonu TODO | Kurulum bitince yeniden başlatma çalışmıyor |
| 9 | C++ backend ölü kod | Derleniyor ama hiçbir yerden çağrılmıyor |
| 10 | Versiyon tutarsızlığı | pubspec.yaml: 1.2.7 vs UI: v2.4.0 |
plan.md şu öncelik sırasını belirliyor:
1. Önce test
2. Sonra boot zinciri
3. Sonra kurulum motoru güvenilirliği
4. Sonra mimari temizlik
5. En son belge
Bu sıraya tamamen sadık kalacağız. Aşağıda Sprint 1'in her adımını detaylandırıyorum.
Sprint 1, plan.md'nin Aşama 0 ve Aşama 1'ini kapsıyor. Toplam 6 ana adım var.
Mevcut CommandRunner sınıfı singleton olarak doğrudan Process.start çağırıyor. Bunu bir soyut sınıf (abstract class) + somut uygulamalar yapısına çevireceğiz.
CommandRunner→abstract class CommandRunnerolacakrun()metoduabstractolacak- Mevcut
Process.startkodu →RealCommandRunnersınıfına taşınacak
FakeCommandRunner implements CommandRunnersınıfı oluşturulacak- Fixture dosyalarından cevap döndürecek
- Test ortamında gerçek komut çalıştırmadan davranış simüle edecek
Şu an CommandRunner.instance her yerde doğrudan kullanılıyor. Bu da demek oluyor ki herhangi bir testi çalıştırabilmek için gerçek bir Linux sisteme ve root yetkisine ihtiyaç var. Bu adımdan sonra:
- Testlerde
FakeCommandRunnerkullanılabilecek - Gerçek kurulumda
RealCommandRunnerkullanılmaya devam edecek - Her servis hangi runner'ı kullandığını bilmeyecek (bağımlılık enjeksiyonu)
- Donanımsız test — Masaüstünde bile test çalıştırılabilir
- Hata senaryoları — "sgdisk başarısız olursa ne olur?" sorusu test edilebilir
- CI/CD uyumluluğu — GitHub Actions'ta bile test çalışabilir
- Geliştirme hızı — Her değişiklik için ISO yazmak gerekmez
// Gerçek kurulumda:
final runner = RealCommandRunner();
// Testlerde:
final runner = FakeCommandRunner({
'lsblk -J -b -o NAME,MODEL,SIZE,TYPE,RM,MOUNTPOINTS':
File('test/fixtures/lsblk_output.json').readAsStringSync(),
});Testlerde kullanılmak üzere sahte komut çalıştırıcısı yazacağız. Bu sınıf:
- Komut + argüman eşleşmesine göre önceden tanımlanmış çıktı döndürür
- Hata senaryolarını simüle edebilir
- Hangi komutların çağrıldığını kaydeder (doğrulama için)
Gerçek disklere, ağa veya sisteme dokunmadan tüm kurulum akışını test edebilirsiniz.
- Güvenli — Yanlışlıkla disk silme riski sıfır
- Hızlı — Test saniyeler içinde biter
- Tekrarlanabilir — Aynı test her seferinde aynı sonucu verir
- Hata simülasyonu — "mkfs.btrfs başarısız olursa akış ne yapar?" test edilebilir
Fedora 43 canlı sistemden örnek komut çıktılarını dosya olarak saklayacağız:
Parser testlerinin gerçekçi veriyle çalışmasını sağlar. Gerçek sistemden toplanan çıktılar "altın standart" (golden test) olarak kullanılır.
- Gerçekçi test verisi — Sentetik değil, gerçek sistem çıktısı
- Regresyon tespiti — Parser bozulursa hemen yakalanır
- Edge case — NVMe, çok diskli, boş disk gibi farklı senaryolar
test('DiskService tek diski doğru parse eder', () {
final runner = FakeCommandRunner({
'lsblk -J -b -o NAME,MODEL,SIZE,TYPE,RM,MOUNTPOINTS':
fixture('lsblk_single_disk.json'),
});
final service = DiskService(runner);
final disks = await service.getDisks();
expect(disks.length, 1);
expect(disks[0]['name'], '/dev/sda');
});DiskService, NetworkService, PartitionService için birim testler yazacağız.
- Tek disk, çok disk, NVMe disk, boş disk, live disk ayrımı testleri
- EFI partition algılama, mevcut OS algılama testleri
- Ethernet bağlı/bağlı değil testleri
- Wi-Fi listesi parse testleri
- SSID'de özel karakter (:) testleri
- Bölüm listesi parse testleri
- Boş alan hesaplama testleri
- Ham disk (bölümsüz) testleri
Disk algılama, ağ tarama ve bölüm okuma kodlarının doğru çalıştığını her kod değişikliğinde otomatik doğrular.
- Erken hata yakalama — Parser bozulursa CI'da düşer
- Güvenli refactoring — Kod yeniden düzenlerken kılavuz olur
- Donanımsız doğrulama — Hiçbir fiziksel disk gerekmez
Kurulum motoru şu an Map<String, dynamic> ile çalışıyor. Bunu tipli bir modele çevireceğiz.
class InstallProfile {
final String selectedDisk;
final String partitionMethod; // 'full', 'alongside', 'manual'
final String fileSystem; // 'btrfs', 'ext4', 'xfs'
final String username;
final String password;
final String timezone;
final String keyboard;
final bool isAdministrator;
final double linuxDiskSizeGB;
final List<Map<String, dynamic>> manualPartitions;
// ...
factory InstallProfile.fromJson(Map<String, dynamic> json);
Map<String, dynamic> toJson();
}- GUI bu modeli doldurur → kurulum motoruna verir
- Test sistemi JSON dosyasından aynı modeli okur → kurulum motoruna verir
- Böylece aynı kurulum senaryosu hem GUI'den hem JSON'dan çalıştırılabilir
- Tip güvenliği —
state['selectedDisk']yerineprofile.selectedDisk - JSON test desteği —
InstallProfile.fromJson(file)ile test senaryosu - Tekrarlanabilir kurulum — Aynı profil ile aynı sonuç
- Hata azaltma — Yanlış key adı veya tip hatası derleme zamanında yakalanır
# Test için JSON profili:
{
"selectedDisk": "/dev/sda",
"partitionMethod": "full",
"fileSystem": "btrfs",
"username": "testuser",
"password": "test1234",
"timezone": "Europe/Istanbul",
"keyboard": "trq",
"isAdministrator": true
}Her stage'in doğru komutları doğru sırada çağırdığını test edeceğiz.
- "full" modda
sgdisk -Z,sgdisk -n 1:0:+512M,sgdisk -n 2:0:0sırasıyla çağrılıyor mu? - Bir komut başarısız olursa stage durduruluyor mu?
partprobeçağrılıyor mu?
- Sıra garantisi — Komutlar yanlış sırada çağrılırsa test düşer
- Hata dayanıklılığı — Başarısız komut sonrası akış testi
- Stage izolasyonu — Her stage bağımsız test edilir
| Sıra | Adım | Bağımlılık | Tahmini Süre |
|---|---|---|---|
| 1 | CommandRunner soyutlama | — | ~30 dk |
| 2 | FakeCommandRunner | Adım 1 | ~20 dk |
| 3 | Fixture dosyaları | — | ~15 dk |
| 4 | Parser/Servis testleri | Adım 1, 2, 3 | ~45 dk |
| 5 | InstallProfile modeli | — | ~30 dk |
| 6 | Stage akış testleri | Adım 1, 2, 5 | ~45 dk |
- QEMU/KVM test laboratuvarı
- Tam kurulum + reboot otomasyonu
- Boot zinciri inceleme ve düzeltme
useradddüzeltmesi- Root parola güvenliği
- Manuel bölümleme kararı
- Mimari temizlik
Important
Bu plan, plan.md'nin Sprint 1 maddelerine tamamen sadık kalarak hazırlanmıştır. İlerlemeye Adım 1: CommandRunner soyutlama ile başlamayı öneriyorum.
Her adımı yapmadan önce size ne yapacağımı açıklayacağım, avantajlarını anlatacağım ve sonra uygulayacağız.
Onaylarsanız, Adım 1 ile başlayalım mı?