GitHub Actions çok daha iyi olabilir
(blog.yossarian.net)- GitHub Actions üretkenlik ve işlevsellik açısından faydalı olsa da, gerçek iş akışı yazımında geciken hata ayıklama, güvenlik hataları, tip eksikliği ve resmi action eksikliği tekrar tekrar zaman kaybına yol açıyor
- Küçük bir düzeltme için bile
git add; git commit; git pushve tarayıcı günlüklerini kontrol etme döngüsünü tekrarlamak gerekiyor; basit bir yayın iş akışında bile 4 commit ve başarısız bir release gerektiği bir örnek var ${{... }}genişletmesi,pull_request_target, geniş varsayılanGITHUB_TOKENyetkileri ve fork SHA referansları, hata yapmaya açık güvenlik noktaları; özellikle fork SHA istenen deponun commit’i gibi görünebiliyor- Action girdilerinde
type:doğrulaması yok veworkflow_callileworkflow_dispatchdestek kapsamı da farklı; bu yüzden dizi/nesne girdileri yerine CSV tarzı dizeleri veya düzleştirilmiş girdileri elle işlemek gerekiyor - Push anında doğrulama, çalışma zamanı güvenlik kontrolleri, özel depolarda varsayılan token yetkilerinin daraltılması, daha sıkı tip kontrolü ve daha fazla resmi/yarı resmi action iş akışı güvenilirliğini artırabilir
Faydalı ama tekrar tekrar ayağa takılan GitHub Actions
- GitHub Actions, 2019’dan beri profesyonel ve hobi projelerinde her gün kullanılacak kadar üretkenliğe ve güven hissine büyük katkı sağlayan bir araç
- Özellik genişletmeleri de düzenli olarak sürdü
- Buna rağmen gerçek geliştirme sürecinde büyük hayal kırıklığı ve zaman kaybı kaynağı da olabiliyor
Hata ayıklama küçük hatalarda bile çok ağır
- Bir release iş akışı kurarken küçük hataları yakalamak için 4 commit ve 4 başarısız release gerektiği bir örnek var
- Gereken yerde
${{ ... }}kullanılmaması needs:ilişkisinin atlanması
- Gereken yerde
- Mevcut hata ayıklama döngüsünde, basit bir hatayı doğrulamak için bile çok sayıda adım gerekiyor
- Geliştirme ortamından tarayıcıya geçmek gerekiyor
- Doğru sekmeyi bulmak gerekiyor
- Actions özeti ve durum ekranına tıklayarak girmek gerekiyor
- Arabelleğe alınmış konsol günlüklerini yenileyip bir sonraki hatayı aramak gerekiyor
- Küçük bir değişiklikte bile tüm süreç 30 saniyeden fazla sürebiliyor
-
İyileştirme yönü
- Etkileşimli hata ayıklama shell’i sağlanmalı ya da en azından
git add; git commit; git pushyapmadan küçük değişikliklerle iş akışı yeniden çalıştırılabilmeli - Depo ayarıyla, açıkça hatalı iş akışları push anında reddedilebilmeli
- Çalışamayacak söz dizimi
- Var olmayan job veya step referansları
- Hatalı YAML yüzünden iş akışının sessizce çalışmaması durumu
- Etkileşimli hata ayıklama shell’i sağlanmalı ya da en azından
Güvenlik hataları çok kolay oluşuyor
- GitHub Actions’ta kullanıcıların yazdığı iş akışlarının istemeden zayıf hale gelmesi kolay
${{ ... }}genişletmesini shell veya başka bir yürütme bağlamında kullanırken, genişletilen değer kullanıcı tarafından kontrol edilen bir girdiyse bu kötü amaçlı kod enjeksiyonuna yol açabilir- Örnekte
inputs.frobüzerinden kod enjekte edilip$MY_IMPORTANT_SECRETsızdırılabiliyor
- Örnekte
pull_request_targetönemsiz olmayan iş akışlarında güvenli kullanımı çok zor- Amaçlanan kullanım örneği, fork’tan gelen PR’lara etiket eklemek veya yorum yazmak gibi dar bir kapsam gibi görünüyor
- Ancak pratikte büyük bir foot-gun gibi ortada duruyor
- İş akışı ve job seviyesindeki yetkiler de kolayca gereğinden fazla verilebiliyor
- Normal
GITHUB_TOKENiçin varsayılan erişim yetkileri çok geniş - Kişisel hesap depolarında varsayılan token yetkilerini daraltmak sıkça unutuluyor
- Gerekli yetki kapsamı tam bilinmediği için token yetkileri aşırı veriliyor
- Normal
- GitHub yetki modelinin tek bir
read/write/noneeksenine sıkıştırılması kafa karışıklığını artırıyorid-token: write, iş akışının OpenID Connect token’ını okuyabilmeyi sağlıyor- Bazı security advisory
GETişlemleriwriteyetkisi isterken, diğerleri yalnızcareadistiyor
SHA ile sabitlenen action’lar fork commit’leriyle karışabiliyor
actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18egibi görünen bir referans aslındaactions/checkoutdeposundaki bir commit olmayabilir- Bu SHA,
actions/checkoutağı içindeki bir fork’ta bulunan bir commit’tir ve GitHub’ın alternates kullanımı nedeniyle üst depoya aitmiş gibi görünebilir - Chainguard’ın ilgili yazısı sorunu üçe ayırıyor
- Fork’un SHA referansı ile hedef deponun SHA referansı görsel olarak ayırt edilmiyor
- GitHub REST API’deki
/repos/{user}/{repo}/commits/{ref},{ref}yalnızca fork’ta olsa bile sadece{user}/{repo}ya referans veren JSON yanıtı döndürüyor - Fork ve fork olmayan SHA’lar ayırt edilemezse GitHub Actions’ın güvenilir kaynak kısıtlaması aşılabiliyor
- GitHub’ın şimdiye kadarki yanıtı belgelere ek bir ifade koymak düzeyinde kaldı
-
İyileştirme yönü
- Açıkça güvenli olmayan iş akışlarını push anında reddeden bir paranoid workflow security modu gerekiyor
- AddressSanitizer benzeri çalışma zamanı enstrümantasyonu gibi, iş akışı çalışırken güvenlik açısından riskli kalıplar başarısız sayılabilmeli
- Örn:
pull_request_targetiçinde hedef depo olmayan bir ref ileactions/checkoutkullanılırsa başarısız olsun
- Örn:
pull_request_targetı kullanım dışı bırakmak veya kaldırmak da değerlendirilebilir- Özel depolarda da organizasyon/enterprise depolarında olduğu gibi varsayılan
GITHUB_TOKENkapsamı daha kısıtlı ayarlanabilmeli - Referans verilen depoda olmayıp yalnızca fork’ta bulunan SHA-pinned action’lar varsayılan olarak reddedilmeli
Tip sistemi tutarlılık ve ifade gücünden yoksun
- Özel GitHub Action,
inputs:altında girdi tanımlayabilir; ancak action girdilerinde tip zorlaması yok type: numbergibi bildirimler action girdilerinde çalışmıyor- GitHub Actions içinde de tip desteğinin bulunduğu yerler tutarlı değil
workflow_call:boolean,number,stringdesteklerworkflow_dispatch:boolean,choice,number,stringdestekler- action inputs: tip desteği yok
- Tip destekleyen girdiler de dizi veya nesne gibi birleşik veri yapılarını desteklemiyor
paths: [foo, bar, baz]gibi dizi girdisi mümkün değilheaders:altında hiyerarşik yapı içeren nesne girdisi mümkün değil
- Action yazarları bunun yerine geçici biçimlerde girdi istemek zorunda kalıyor
paths: foo,bar,bazgibi CSV tarzı ayrıştırmayı elle uygulamakheader-foo,header-bazgibi doğal hiyerarşik yapıyı düzleştirmek
- Bu yaklaşım hem sürdürülebilirlik hem de güvenlik için iyi değil
- Tek bir düz girdi ad alanını elle yönetmek gerekiyor
- Karmaşık girdiler için keyfi, belirtilmemiş diller oluşturuluyor
-
İyileştirme yönü
- Action ve workflow yazarları
type:ı her yerde kullanabilmeli choiceda yalnızcaworkflow_dispatchile sınırlı kalmadan her yerde kullanılabilmeli- Statik olarak tip çıkarımı yapılabilen durumlarda, hatalı tip içeren iş akışı değişiklikleri push anında reddedilmeli
type: objectvetype: arraygerekiyor- İç tipler heterojen olabileceği için mükemmel olmasa da mevcut durumdan daha iyi olabilir
- Gerekirse JSON olarak serileştirilmiş dizeyle aktarılabilir
- GitHub Actions’ta zaten
fromJSON(...)fonksiyonu var
- Action ve workflow yazarları
Resmi action’lar platform güveniyle doğrudan bağlantılı
- GitHub Actions’ın üçüncü taraf ekosisteminde çok sayıda yüksek kaliteli action var
- Bunların altında GitHub’ın bakımını yaptığı resmi action’lar bulunuyor
- Temel
gitişleri:actions/checkout - GitHub işleri ve depo yönetimi:
actions/{upload,download}-artifact,actions/cache,actions/stale - Gerekli kurulumlar:
actions/setup-python,actions/setup-node
- Temel
- Bu action’ların genel amaçlılığı ve önemi yüksek olduğundan, resmi olarak bakımı yapılan bir uygulamanın değeri büyük
- Ancak resmi action sayısı az ve GitHub özelliklerini doğrudan bağlayan işler de bazen resmi action olarak sunulmuyor
- Örn: bir pull request’i programatik olarak merge queue’ya ekleyen action
- GitHub CLI’da
gh pr mergevar, ancak action olarak açığa çıkarılmıyor
-
Durdurulan resmi action örnekleri
actions/create-release: Mart 2021’den beri bakımı durduruldu- Kullanıcılara topluluk tarafından bakımı yapılan iş akışlarına geçmeleri öneriliyor
- Temsili olarak
softprops/action-gh-releasebelirtiliyor actions/upload-release-asset:actions/create-releaseile aynı dönemde bakımı durduruldu olarak işaretlendiactions/setup-ruby: Şubat 2021’den beri bakımı durduruldu- Kullanıcılara
ruby/setup-ruby’ye geçmeleri öneriliyor - Geçişin kendisi görece az sancılı olsa da, temel bileşenlerin terk edilebileceği izlenimi platform güvenini olumsuz etkiliyor
- Resmi, yüksek kaliteli action’lar eksik olduğunda kullanıcılar GitHub API yüzeyiyle doğrudan uğraşıp güvenlik hataları yapmaya devam edebiliyor
-
Ekosistem için iyileştirme yönü
- GitHub altyapısının farklı parçalarını doğrudan birbirine bağlayan ve bugün REST API çağrıları ya da
ghçalıştırma ile elle yapılan işler, resmi action olarak sunulmaya değer - Büyük üçüncü taraf action’larla iş birliği yapılarak
community-actionsgibi yarı resmi bir organizasyon kurulabilir- GitHub tarafından incelenmiş action’lar
- Depo güvenliği en iyi uygulamalarına uyum
- Semantik sürüm güncellemeleri
- Önemli ekosistem action’ları için net bir güven yolu
- GitHub altyapısının farklı parçalarını doğrudan birbirine bağlayan ve bugün REST API çağrıları ya da
Mevcut araçlar ve GitHub yol haritası
- Birçok kişi yerel GitHub Actions emülasyon aracı olan
nektos/act’i öneriyor- Basit iş akışlarını hızla yinelemek ve hata ayıklamak için faydalı
- Ancak imajlar ve event’ler GitHub’ın gerçek ortamıyla her zaman tamamen aynı olmayabildiğinden kayıplı bir araç olarak değerlendiriliyor
rhysd/actionlintyerel linting ve güvenlik linting’i için kullanılıyor- Yalnızca workflows üzerinde lint çalıştırabilmesi, actions üzerinde çalıştıramaması bir sınırlama
- VS Code için GitHub Actions eklentisi, editör içi lint ve depo iş akışı entegrasyonu sağlıyor
- Açık JSON schema tabanlı
- Çalışan workflow’ları gösterme, değişken tamamlama vb. sağlıyor
- Ancak secrets yazım hataları veya dinamik olarak oluşturulan output adlarındaki yazım hataları gibi sorunları yakalayamadığı için add-commit-push hata ayıklaması hâlâ gerekli
- GitHub Actions proje yönetimi sorumlusu Julian Dunn, devam eden bazı özellikleri ve öncelikleri paylaştı
- Etkileşimli hata ayıklama, GitHub Actions’ın açık yol haritasında yer alıyor
- Tag/SHA tabanlı workflow pinning’den daha değişmez bir yaklaşıma geçme çalışması da açık yol haritasında yer alıyor
- GitHub, resmi action ekosisteminin sağlığını ve kalitesini öncelik olarak görüyor; her action’a yeterli bakım ve ilgi verebilmek için resmi action sayısını küçük tutma stratejisini benimsiyor
1 yorum
Hacker News yorumları
GitHub Actions iş akışlarında iki yaklaşım var. 1) GitHub Actions ile “programlama” yapıp e-posta gönderme gibi şeyler için de marketplace araçları eklemek; YAML’ın 500–1000 satıra büyümesi ve koşul ifadeleriyle dolup anlaşılması zor hâle gelmesi
2) GitHub Actions’ı yalnızca “yapılandırmak” ve sürekli “bu YAML karmaşıklığını bir script’e itebilir miyim?” diye sormak. E-posta göndermeyi de script’e koyarsanız iş akışı yaklaşık 50–60 satırda biter; script’i yerelde debug edebildiğiniz için aptalca push-debug-commit döngüsü de neredeyse ortadan kalkar. Yeni bir ekibe her gittiğimde 1’in delilik yolu, 2’nin ise mantıklı olduğunu söylüyorum; ama yaklaşık yarısı hâlâ 1’i seçiyor. Debug araçlarının eksikliği ve vendor lock-in de 2’yi seçince çok daha az sorun oluyor
Ancak her şeyi düzgün bir programlama diline taşımak çoğu zaman tek başına yeterli olmayabiliyor. GHA’nın vendora özgü özelliklerini kullanmanız, işler arasındaki bağımlılıkları göstermeniz ya da zaten bir action olarak iyi soyutlanmış bir REST API’yi çağırmanız gereken durumlar oluyor. İstediğiniz dilde yeniden uygulayabilirsiniz ama bu vendor bağımlılığını ortadan kaldırmaz ve hâlâ kırılgandır. Sonuçta GHA’nın vendor lock-in değer önerisi çok güçlü; insanları 2 numaraya ikna etmek için daha güçlü avantajlar gerekiyor
Bu yalnızca GHA için değil, tüm build sunucuları için geçerli. Build sunucusu; geçmiş, artifact yönetimi, yetki/audit ekleyen bir script çalıştırıcı olmalı; gerçek build sürecini ise build hedefi olan depoya devretmelidir
Bu arada GHA davranışını yerelde yeniden üretmeye çalışan nektos/act var: https://github.com/nektos/act
Build/test/imzalama/dağıtım vb. işleri mümkün olduğunca taşınabilir script’ler olarak yazmalı; bu script’ler her zaman yerelde çalışmalıdır. GitHub’ı yalnızca bu script’leri çalıştıracak ortamı otomatik hazırlayan ve fiilen çalıştıran bir rol olarak görüyorum
git commit, push, wait döngüsü korkunç bir kullanıcı deneyimi. Kullanıcılar, yerel makine dahil her yerde çalışan taşınabilir pipeline’ları hak ediyor. Act bu sorunu bir ölçüde çözüyor ama genelde gerçek ortamı birebir temsil etmiyor
Production gibi yerelde çalıştırılamayan birçok pipeline var; ancak daha az kritik geliştirme aşamalarında bu tür workflow’ları yakalayıp yerelde çalıştırmamak için bir neden yok. Garden taşınabilir pipeline’lar sunuyor ve tüm bağımlılık grafiği genelinde caching ekliyor. Bazı müşterilerde çalışma süresi %80’den fazla azaldı; geliştiriciler de önce git’e push etmeden testlerin geçtiğini/kaldığını anında görüyor. Açık kaynak: https://github.com/nektos/act, https://docs.garden.io
make releasegibi aynı hedef/komutları kullanmalıGH Actions çalıştırmalarını debug etmenin acısına tamamen katılıyorum. Elimizdeki tek araç debug’ı açıp yeniden çalıştırma özelliği. Pipeline’ı düzeltmek ya da debug etmek için yapılmış çöp commit sayısı çok fazla; çoğu da çalışıyor mu diye rastgele deneme atmaktan ibaret
Yeniden kullanılabilir mantık gibi çok temel işler bile gereksiz yere karmaşık ya da kötü belgelenmiş. Öğrendikten sonra oldukça kolaydı ama GitHub dokümantasyonu berbattı. Yeniden kullanılabilirlik elde etmek için action’ı public yapmak ya da başka bir depoya koymak gerekiyormuş gibi görünüyordu; oysa aslında yeniden kullanılabilir mantığı içeren yeni bir YAML dosyası oluşturabiliyorsunuz. Ancak çalışması için workflows klasörünün kökünde durması gerekiyor. GH Actions ile çalışmak gerçekten acı verici ama bir kez çalışınca çok kullanışlı. Commit edip push etmeden önce action’ı test edebileceğimiz bir yerel runner olsa iyi olurdu
Bu yalnızca GitHub’ın sorunu da değil. Diğer büyük CI platformları da workflow ve entegrasyon açısından pek daha iyi değil. Şimdi mümkün olduğunca her şeyi script’leştiriyorum
GitHub Actions berbat bir CI/CD sistemi. Aynı VM üzerinde adımları paralel çalıştıramıyor ve container tabanlı işler ikinci sınıf vatandaş muamelesi görüyor
İlk sorun yüzünden yerel kimlik bilgileri ya da ortam bağımlılığı kurulumlarını paralelleştiremiyorsunuz.
google-github-actions/setup-gcloud’un 1 dakikadan uzun sürdüğünü görünce sinirleniyorum. İkinci sorun yüzünden CI ortamı ayarını depodaki Dockerfile ile ifade etmek; imaj içeriği değişirse CI’ın imajı yeniden build edip o imaja bağımlı workflow’ları bekletmesi; içerik değişmemişse yeniden build etmeden, önceden kurulmuş bağımlılıklarla hemen çalıştırması gibi bir yapı kurmak çok zor. GitHub Actions’ta her seferinde cache’i yeniden doldurmaya çalışır hâle geliyorsunuz. Cache’in 5 GB sınırı var, para ödeseniz de artıramıyorsunuz ve FIFO ile dışarı atıldığı için 5 GB’ı aşınca fiilen yok hükmünde. Concourse’u gerçekten özlüyorum. Paralel işler, kullanıcı tanımlı pipeline tetikleyicileri, CI ortamına SSH ile girip debug etme, pipeline olmadan tek seferlik iş çalıştırma, çıktı üretmeden işler arasında dizin içeriği aktarma gibi şeyler mümkündü. GitHub Actions,.github/workflowsiçine tek bir dosya koyunca hemen kullanılabilmesi sayesinde popüler olmuş bir oyuncak CI/CD’ye daha yakın. İnsanları içeri almak için iyi ama başlangıç özelliklerinin ötesine geçince “en iyisi” denecek kadar güçlü değilSSH debug ve tek seferlik işler gerçekten rüya gibiydi
GitHub’ın fork ile non-fork SHA referanslarını ayırt edememesi nedeniyle bir fork’un GitHub Actions güvenlik ayarlarını aşabilmesi meselesinin hâlâ nasıl çözülmediğini bilmiyorum
Güvenlik kontrolleri kolayca aşılabiliyorsa bu ciddi bir güvenlik sorunudur. Birini benim SHA’ımı kullanmaya ikna etmek gerekiyor gerçi, ama sosyal mühendislik genellikle kolay taraftadır
Dürüst olmak gerekirse ne kadar kötü olduğu utanç verici. Alakasız build hatalarının tesadüfen en son merge yapan maintainer’a bildirilmesi de tuhaf. Yeni eklenen bir maintainer Matrix üzerinden haber verene kadar güncellememin/build’imin bir haftadır başarısız olduğunu fark etmeyebilirim
cache action gözle görülür biçimde bariz şekilde bozuk ama bir yöneticisi yok gibi görünüyor. UI bozulursa ya da sekme unload edilirse adımın build log’unu tail etmek bile mümkün değil. Workflow’ları worker node’lar arasında taşınabilir kılacak bir soyutlama da fiilen yok. Varsayılan imajlar felakete yakın. Başta yalnızca fazla şişkin olduğu için sinir bozucuydu; ama içine indikçe “Linux’u bilmeyen bir Microsoft çalışanına kalmış” diye düşündüm. Nix ya da Docker kullananlar için daha hafif imajlar sunmaya yönelik bir çaba da yok. GitHub’dan uzaklaşıyorum; başlıca nedeni Actions’ın beni kendime getirmesi oldu. YAML ile programlama yapmamamızın nedeni, YAML’i modern ve gerçekten işe yarar teknolojileri bilmeyen bir ekosistemin üzerine VC parasının yağmasıyla ortaya çıkmış bir utanç olarak görmem
https://pre-commit.ci'yi şiddetle tavsiye ederim. İlgili bir kişi değilim, sadece memnun bir kullanıcıyım.
Fikir şu: commit öncesinde kodu denetleyen ve mümkünse düzelten hook'lar yazmak ya da mevcut hook'ları kullanmak; push sonrasında CI'ın tekrar denetlemesi ve gerekirse otomatik düzeltme commit'i bile yapması. Otomatik önbelleklemesi iyi olduğu için inanması zor derecede hızlı ve yerel geliştirme makinesi ile CI'da aynı yapılandırma kullanıldığı için hata ayıklama sorunları ciddi ölçüde azalıyor. Açık kaynak için ücretsiz. Otomatik release gibi şeyler yapmıyor, yalnızca denetliyor; ama bu denetimi çok iyi yapıyor.
Kaynak kodun kendisini denetlemek için
skip_install = Trueile statik kontroller de çalıştırılabilir. tox'un global araç olarak kurulu olduğu ve gerekli tüm Python sürümlerini içeren bir container'da çalıştırmak yeterli. Örneğin https://github.com/georgek/docker-python-multiversion gibi bir imaj var. Bakımı yapılmıyor ama güncellemesi kolay.[tox] envlist = py{310,311},[testenv],[testenv:check]içindepre-commit run --all-files --show-diff-on-failurekoyan türden bir boilerplate yeterli.git commit; git push; repeatdöngüsünü çok fazla yaşadıktan sonra https://github.com/mxschmitt/action-tmate'i keşfettim. Adımlar arasında shell erişimi açıyor; tüm sorunları çözmüyor ama bazen acıyı kesinlikle azaltıyor.Kişisel olarak, şu anda
actions/upload-artifactgibi bir şey kullanmadan bir action run'a HTML raporu ekleyebilmek isterdim.Özellikle test build'lerinde çıktı HTML raporunu hızlıca görmek istediğiniz durumlar çok oluyor. Şu an bildiğim yöntemler upload-artifact ya da GH Pages; ancak GH Pages, aynı depoda birden fazla rapor çıktısı olduğunda veya en güncel olanı değil de geçmiş bir raporu hızlıca görmek istediğinizde pek iyi değil. İş özetine bir HTML raporu bağlantısı ekleyen ve tıklayınca HTML'i render eden basit bir
attach-reportaction'ı olsa iyi olurdu. Diğer otomasyon CI/CD sistemleri, HTML raporlarını yakalama ve görüntüleme konusunda varsayılan olarak çok daha zengin destek sunuyor.$GITHUB_STEP_SUMMARY'ye doğrudan Markdown çıktısı ekleyebilirsiniz.GH Actions'ın fiilen Microsoft'un “Azure Pipelines” için yaptığı bir rebranding'e yakın olduğunu düşünüyorum. TFS/VSTS/AzDO build ve release pipeline'larının önceki biçimlerinin hepsini kullanmış biri olarak, bu ekip bu işi iyi yapamıyor.
Azure Pipelines'ın az çok kullanılabilir hale gelmesi bile ondan önce denedikleri tüm yaklaşımların kelimenin tam anlamıyla başarısız olmasından kaynaklanıyordu. Commit atmadan kişisel ortamda edit-run-debug döngüsü döndürebilmek için pipeline'ları yerelde çalıştıran bir proje de vardı ama doğal olarak iptal edildi: https://github.com/microsoft/azure-pipelines-agent/pull/2687/files#diff-570b52bcb927a5365c22d17a21e8e19e1ba3427c7f3ec16ea64b7b3d14e4ee20. Yine de yaşam kalitesini artıran araçlar var. Örneğin sözdizimini tanıyan VS Code eklentisi: https://marketplace.visualstudio.com/items?itemName=ms-azure-devops.azure-pipelines. Biraz tartışmalı söylemek gerekirse YAML yerine XML kullanılsaydı, en üstteki xmlns bildirimi tek başına bile iyi kod editörlerinin çoğunda ayrıca kullanıcı müdahalesi olmadan doğrulama sağlayabilirdi. XML berbat, ama onu tamamen çöpe atarken beraberinde kaybettiğimiz çok sayıda faydalı özellik de var.