Bazel Kilit Dosyası

Bazel'deki kilit dosyası özelliği, bir proje için gereken yazılım kitaplıklarının veya paketlerin belirli sürümlerinin ya da bağımlılıklarının kaydedilmesini sağlar. Bu, modül çözünürlüğünün ve uzantı değerlendirmesinin sonucunu depolayarak gerçekleştirilir. Kilit dosyası, tutarlı geliştirme ortamları sağlayarak yeniden üretilebilir derlemeleri destekler. Ayrıca, Bazel'in proje bağımlılıklarındaki değişikliklerden etkilenmeyen çözümleme süreci kısımlarını atlamasına izin vererek derleme verimliliğini artırır. Ayrıca, kilit dosyası, harici kitaplıklarda beklenmedik güncellemeleri veya değişiklikleri önleyerek kararlılığı artırır ve böylece hata oluşma riskini azaltır.

Kilit dosyası oluşturma

Kilit dosyası, çalışma alanı kökü altında MODULE.bazel.lock adıyla oluşturulur. Derleme işlemi sırasında, özellikle modül çözümü ve uzantı değerlendirmesinden sonra oluşturulur veya güncellenir. Önemli olarak, yalnızca derlemenin mevcut çağrılmasına dahil edilen bağımlılıkları içerir.

Projede bağımlılıklarını etkileyen değişiklikler olduğunda, kilit dosyası yeni durumu yansıtacak şekilde otomatik olarak güncellenir. Bu, kilit dosyasının mevcut derleme için gereken belirli bağımlılıklar kümesine odaklanmasını sağlayarak projenin çözümlenmiş bağımlılıklarının doğru bir şekilde gösterilmesini sağlar.

Lockfile Kullanımı

Proje durumu kilit dosyasından farklı olduğunda Bazel'in davranışını özelleştirmek için kilit dosyası --lockfile_mode işaretiyle kontrol edilebilir. Kullanılabilir modlar şunlardır:

  • update (Varsayılan): Bilinen kayıt dosyalarının indirilmesini atlamak ve sonuçları hâlâ güncel olan uzantıların yeniden değerlendirilmesini önlemek için kilit dosyasında bulunan bilgileri kullanın. Eksik bilgiler varsa kilit dosyasına eklenir. Bu modda Bazel, değişmeyen bağımlılıklar için iptal edilen sürümler gibi değiştirilebilir bilgileri de yenilemez.
  • refresh: update'a benzer ancak bu moda geçildiğinde ve bu moddayken yaklaşık her saatte bir değiştirilebilir bilgiler yenilenir.
  • error: update gibi, ancak herhangi bir bilgi eksikse veya güncel değilse Bazel hata vererek başarısız olur. Bu mod, çözümleme sırasında hiçbir zaman kilit dosyasını değiştirmez veya ağ istekleri gerçekleştirmez. Kendilerini reproducible olarak işaretleyen modül uzantıları, ağ istekleri gerçekleştirmeye devam edebilir ancak her zaman aynı sonucu üretmesi beklenir.
  • off: Kilit dosyası ne kontrol edilir ne de güncellenir.

Lockfile'ın avantajları

Kilit dosyası çeşitli avantajlar sunar ve farklı şekillerde kullanılabilir:

  • Yeniden üretilebilir derlemeler. Kilit dosyası, yazılım kitaplıklarının belirli sürümlerini veya bağımlılıklarını yakalayarak derlemelerin farklı ortamlarda ve zaman içinde yeniden üretilebilir olmasını sağlar. Geliştiriciler, projelerini oluştururken tutarlı ve tahmin edilebilir sonuçlar elde edebilir.

  • Hızlı artımlı çözümler. Kilit dosyası, Bazel'in önceki bir derlemede zaten kullanılmış olan kayıt dosyalarını indirmesini engeller. Bu, özellikle çözümlemenin zaman alabileceği senaryolarda derleme verimliliğini önemli ölçüde artırır.

  • Kararlılık ve risk azaltma. Kilit dosyası, harici kitaplıklarda beklenmedik güncellemeleri veya önemli değişiklikleri önleyerek kararlılığın korunmasına yardımcı olur. Bağımlılıkları belirli sürümlere kilitleyerek uyumsuz veya test edilmemiş güncellemeler nedeniyle hata oluşma riski azaltılır.

Gizli kilit dosyası

Bazel ayrıca "$(bazel info output_base)"/MODULE.bazel.lock konumunda başka bir kilit dosyası tutar. Bu kilit dosyasının biçimi ve içeriği açıkça belirtilmemiştir. Yalnızca performans optimizasyonu olarak kullanılır. bazel clean --expunge aracılığıyla çıktı tabanıyla birlikte silinebilse de bunu yapma ihtiyacı, Bazel'in kendisinde veya bir modül uzantısında bir hatadır.

Lockfile İçeriği

Kilit dosyası, proje durumunun değişip değişmediğini belirlemek için gerekli tüm bilgileri içerir. Ayrıca, projenin mevcut durumda oluşturulmasının sonucu da yer alır. Kilit dosyası iki ana bölümden oluşur:

  1. Modül çözümlemesine giriş olarak kullanılan tüm uzak dosyaların karma değerleri.
  2. Her modül uzantısı için kilit dosyası, bzlTransitiveDigest, usagesDigest ve diğer alanlarla gösterilen, uzantıyı etkileyen girişlerin yanı sıra generatedRepoSpecs olarak adlandırılan uzantının çalıştırılmasının sonucunu içerir.

Aşağıda, kilit dosyasının yapısını gösteren bir örnek ve her bölümle ilgili açıklamalar verilmiştir:

{
  "lockFileVersion": 10,
  "registryFileHashes": {
    "https://bcr.bazel.build/bazel_registry.json": "8a28e4af...5d5b3497",
    "https://bcr.bazel.build/modules/foo/1.0/MODULE.bazel": "7cd0312e...5c96ace2",
    "https://bcr.bazel.build/modules/foo/2.0/MODULE.bazel": "70390338... 9fc57589",
    "https://bcr.bazel.build/modules/foo/2.0/source.json": "7e3a9adf...170d94ad",
    "https://registry.mycorp.com/modules/foo/1.0/MODULE.bazel": "not found",
    ...
  },
  "selectedYankedVersions": {
    "foo@2.0": "Yanked for demo purposes"
  },
  "moduleExtensions": {
    "//:extension.bzl%lockfile_ext": {
      "general": {
        "bzlTransitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    },
    "//:extension.bzl%lockfile_ext2": {
      "os:macos": {
        "bzlTransitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
        "usagesDigest": "aLmqbvowmHkkBPve05y....yDNGN7oh7r3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      },
      "os:linux": {
        "bzlTransitiveDigest": "eWDzxG/aLsyY3Ubrto....+Jp4maQvEPxn0pLK=",
        "usagesDigest": "aLmqbvowmHkkBPve05y....yDNGN7oh7r3QIZTZs=",
        ...,
        "generatedRepoSpecs": {
          "hello": {
            "bzlFile": "@@//:extension.bzl",
            ...
          }
        }
      }
    }
  }
}

Kayıt defteri dosyası karmaları

registryFileHashes bölümü, modül çözümü sırasında erişilen uzak kayıt defterlerindeki tüm dosyaların karma değerlerini içerir. Çözümleme algoritması, aynı girişler verildiğinde tamamen deterministik olduğundan ve tüm uzak girişler karma oluşturma işlemine tabi tutulduğundan, bu durum, kilit dosyasında aşırı uzak bilgi kopyalanmasını önlerken tamamen yeniden üretilebilir bir çözümleme sonucu sağlar. Bunun, belirli bir kayıt defteri belirli bir modülü içermediğinde ancak daha düşük önceliğe sahip bir kayıt defteri içerdiğinde de kayıt gerektirdiğini unutmayın (örnekteki "bulunamadı" girişine bakın). Doğası gereği değişebilir olan bu bilgiler bazel mod deps --lockfile_mode=refresh aracılığıyla güncellenebilir.

Bazel, indirmeden önce kayıt dosyalarını depodaki önbellekte aramak için kilit dosyasındaki karma değerlerini kullanır. Bu da sonraki çözümleri hızlandırır.

Seçilen geri çekilmiş sürümler

selectedYankedVersions bölümü, modül çözümleme tarafından seçilen modüllerin kaldırılmış sürümlerini içerir. Bu durum genellikle derleme sırasında hataya neden olduğundan bu bölüm yalnızca --allow_yanked_versions veya BZLMOD_ALLOW_YANKED_VERSIONS aracılığıyla açıkça izin verilen yanked sürümler için boş değildir.

Bu alan, modül dosyalarına kıyasla geri çekilen sürüm bilgilerinin doğası gereği değiştirilebilir olması ve bu nedenle karma ile referans verilememesi nedeniyle gereklidir. Bu bilgiler bazel mod deps --lockfile_mode=refresh üzerinden güncellenebilir.

Modül Uzantıları

moduleExtensions bölümü, yalnızca mevcut çağrıda veya daha önce çağrılan uzantıları içeren, artık kullanılmayan uzantıları ise hariç tutan bir haritadır. Başka bir deyişle, bir uzantı bağımlılık grafiğinde artık kullanılmıyorsa moduleExtensions haritasından kaldırılır.

Bir uzantı işletim sisteminden veya mimari türünden bağımsızsa bu bölümde yalnızca tek bir "genel" giriş bulunur. Aksi takdirde, işletim sistemine, mimariye veya her ikisine göre adlandırılmış birden fazla giriş eklenir. Her giriş, uzantının bu özellikler üzerinde değerlendirilmesinin sonucuna karşılık gelir.

Uzantı eşlemesindeki her giriş, kullanılan bir uzantıya karşılık gelir ve içerdiği dosya ve adıyla tanımlanır. Her girişin karşılık gelen değeri, bu uzantıyla ilişkili bilgileri içerir:

  1. bzlTransitiveDigest, uzantı uygulamasının ve bu uygulama tarafından geçişli olarak yüklenen .bzl dosyalarının özetidir.
  2. usagesDigest, tüm etiketleri içeren bağımlılık grafiğindeki uzantı kullanımlarının özetidir.
  3. Uzantıya yapılan diğer girişleri izleyen, belirtilmemiş diğer alanlar (ör. okuduğu dosyaların veya dizinlerin içeriği ya da kullandığı ortam değişkenleri).
  4. generatedRepoSpecs, uzantı tarafından oluşturulan depoları mevcut girişle kodlar.
  5. İsteğe bağlı moduleExtensionMetadata alanı, uzantı tarafından sağlanan meta verileri içerir. Örneğin, oluşturduğu belirli depoların kök modül tarafından use_repo aracılığıyla içe aktarılıp aktarılmayacağı gibi. Bu bilgiler, bazel mod tidy komutunu destekler.

Modül uzantıları, reproducible = True ile döndürülen meta verileri ayarlayarak kilit dosyasına dahil edilmeyi devre dışı bırakabilir. Bunu yaparak, aynı girişler verildiğinde her zaman aynı depoları oluşturacaklarını taahhüt ederler.

En İyi Uygulamalar

Kilit dosyası özelliğinin avantajlarından en iyi şekilde yararlanmak için aşağıdaki en iyi uygulamaları göz önünde bulundurun:

  • Proje bağımlılıklarındaki veya yapılandırmadaki değişiklikleri yansıtmak için kilit dosyasını düzenli olarak güncelleyin. Bu sayede, sonraki derlemelerin en güncel ve doğru bağımlılık kümesine dayalı olması sağlanır. Tüm uzantıları aynı anda kilitlemek için bazel mod deps --lockfile_mode=update komutunu çalıştırın.

  • İşbirliğini kolaylaştırmak ve tüm ekip üyelerinin aynı kilit dosyasına erişmesini sağlamak için kilit dosyasını sürüm kontrolüne dahil edin. Bu sayede, proje genelinde tutarlı geliştirme ortamları sağlanır.

  • Bazel'i çalıştırmak için bazelisk komutunu kullanın ve kilit dosyasına karşılık gelen Bazel sürümünü belirten bir .bazelversion dosyasını sürüm kontrolüne ekleyin. Bazel'in kendisi derlemenizin bağımlılığı olduğundan kilit dosyası Bazel sürümüne özeldir ve geriye dönük uyumlu Bazel sürümleri arasında bile değişir. bazelisk kullanıldığında tüm geliştiricilerin kilit dosyasıyla eşleşen bir Bazel sürümü kullandığından emin olunur.

Bu en iyi uygulamaları izleyerek Bazel'deki kilit dosyası özelliğini etkili bir şekilde kullanabilir, böylece daha verimli, güvenilir ve işbirlikçi yazılım geliştirme iş akışları oluşturabilirsiniz.

Birleştirme Çakışmaları

Kilit dosyası biçimi, birleştirme çakışmalarını en aza indirecek şekilde tasarlanmıştır ancak yine de çakışmalar yaşanabilir.

Otomatik Çözüm

Bazel, bu çakışmaları otomatik olarak çözmeye yardımcı olmak için özel bir git merge sürücüsü sağlar.

Bu satırı, Git deponuzun kökündeki bir .gitattributes dosyasına ekleyerek sürücüyü ayarlayın:

# A custom merge driver for the Bazel lockfile.
# https://bazel.build/external/lockfile#automatic-resolution
MODULE.bazel.lock merge=bazel-lockfile-merge

Ardından, sürücüyü kullanmak isteyen her geliştiricinin aşağıdaki adımları uygulayarak sürücüyü bir kez kaydetmesi gerekir:

  1. jq'yu (1.5 veya sonraki sürümler) yükleyin.
  2. Aşağıdaki komutları çalıştırın:
jq_script=$(curl https://raw.githubusercontent.com/bazelbuild/bazel/master/scripts/bazel-lockfile-merge.jq)
printf '%s\n' "${jq_script}" | less # to optionally inspect the jq script
git config --global merge.bazel-lockfile-merge.name   "Merge driver for the Bazel lockfile (MODULE.bazel.lock)"
git config --global merge.bazel-lockfile-merge.driver "jq -s '${jq_script}' -- %O %A %B > %A.jq_tmp && mv %A.jq_tmp %A"

Manuel Çözüm

registryFileHashes ve selectedYankedVersions alanlarındaki basit birleştirme çakışmaları, çakışmanın her iki tarafındaki tüm girişler korunarak güvenli bir şekilde çözülebilir.

Diğer birleştirme çakışmaları manuel olarak çözülmemelidir. Bunun yerine:

  1. git reset MODULE.bazel.lock && git checkout MODULE.bazel.lock ile kilit dosyasının önceki durumunu geri yükleyin.
  2. MODULE.bazel dosyasındaki çakışmaları giderin.
  3. Kilit dosyasını güncellemek için bazel mod deps komutunu çalıştırın.