Bazel ile günlük etkileşim öncelikle birkaç komut aracılığıyla gerçekleşir:
build
, test
ve run
. Bununla birlikte, bazen bu kapasite kısıtlı olabilir: Paketleri bir depoya aktarmak, son kullanıcılar için belge yayınlamak veya Kubernetes ile uygulama dağıtmak isteyebilirsiniz. Ancak Bazel'de publish
veya deploy
komutu yoktur. Bu işlemler nerede kullanılır?
bazel run komutu
Bazel'in hermetiklik, yeniden üretilebilirlik ve artımlılığa odaklanması, build
ve test
komutlarının yukarıdaki görevler için yararlı olmadığı anlamına gelir. Bu işlemler, sınırlı ağ erişimi olan bir korumalı alanda çalışabilir ve her bazel build
ile yeniden çalıştırılmaları garanti edilmez.
Bunun yerine, bazel run
'ten yararlanın: İstediğiniz yan etkilerin olduğu görevler için idealdir. Bazel kullanıcıları yürütülebilir dosyalar oluşturan kurallara alışkındır. Kural yazarları, bunu "özel fiillere" genişletmek için ortak bir kalıplar dizisini izleyebilirler.
Doğada: rules_k8s
Örneğin, Bazel için Kubernetes kurallarını içeren rules_k8s
dosyasını ele alalım. Aşağıdaki hedefe sahip olduğunuzu varsayalım:
# BUILD file in //application/k8s
k8s_object(
name = "staging",
kind = "deployment",
cluster = "testing",
template = "deployment.yaml",
)
staging
hedefinde bazel build
kullanıldığında k8s_object
kuralı standart bir Kubernetes YAML dosyası oluşturur. Bununla birlikte, ek hedefler staging.apply
ve :staging.delete
gibi adlara sahip k8s_object
makrosu tarafından da oluşturulur. Bu komutlar, söz konusu işlemleri gerçekleştirmek için komut dosyaları oluşturur ve bazel run
staging.apply
ile çalıştırıldığında kendi bazel k8s-apply
veya bazel
k8s-delete
komutlarımız gibi davranır.
Başka bir örnek: ts_api_guardian_test
Bu kalıp Angular projesinde de görülebilir. ts_api_guardian_test
makrosu iki hedef oluşturur. Bunlardan ilki, oluşturulan bazı çıkışları "altın" bir dosyayla (yani beklenen çıkışı içeren bir dosya) karşılaştıran standart bir nodejs_test
hedefidir. Bu özellik, normal bir bazel
test
çağrısıyla derlenip çalıştırılabilir. angular-cli
'te, bazel test //etc/api:angular_devkit_core_api
ile böyle bir hedef çalıştırabilirsiniz.
Bu altın dosyanın zaman içinde geçerli nedenlerle güncellenmesi gerekebilir.
Bu dosyayı manuel olarak güncellemek zahmetli ve hatalara açık bir işlemdir. Bu nedenle, bu makroda altın dosyayla karşılaştırmak yerine dosyayı güncelleyen bir nodejs_binary
hedefi de sağlanır. Aynı test komut dosyası, çağrılış şekline bağlı olarak "doğrula" veya "kabul et" modunda çalışacak şekilde yazılabilir. Bu, daha önce öğrendiğiniz kalıbı takip eder: Yerleşik bir bazel test-accept
komutu yoktur ancak aynı etki bazel run //etc/api:angular_devkit_core_api.accept
ile elde edilebilir.
Bu kalıp oldukça güçlü olabilir ve tanımayı öğrendikten sonra oldukça yaygın olduğunu görebilirsiniz.
Kendi kurallarınızı uyarlama
Bu modelin merkezinde makrolar yer alır. Makrolar kurallar gibi kullanılır ancak birden fazla hedef oluşturabilir. Genellikle, birincil derleme işlemini gerçekleştiren, belirtilen ada sahip bir hedef oluştururlar: Normal bir ikili dosyayı, Docker görüntüsünü veya kaynak kodu arşivini derleyebilirler. Bu kalıpta, birincil hedefin çıktısına göre yan etkiler gerçekleştiren komut dosyaları oluşturmak için ek hedefler oluşturulur (ör. ortaya çıkan ikili dosyayı yayınlama veya beklenen test çıktısını güncelleme).
Bunu açıklamak için, Sphinx ile web sitesi oluşturan hayali bir kuralı, kullanıcının hazır olduğunda yayınlamasına olanak tanıyan ek bir hedef oluşturmak için bir makroyla sarmalayın. Sphinx ile web sitesi oluşturmak için aşağıdaki mevcut kuralı göz önünde bulundurun:
_sphinx_site = rule(
implementation = _sphinx_impl,
attrs = {"srcs": attr.label_list(allow_files = [".rst"])},
)
Ardından, aşağıdaki gibi bir kural düşünün. Bu kural, çalıştırıldığında oluşturulan sayfaları yayınlayan bir komut dosyası oluşturur:
_sphinx_publisher = rule(
implementation = _publish_impl,
attrs = {
"site": attr.label(),
"_publisher": attr.label(
default = "//internal/sphinx:publisher",
executable = True,
),
},
executable = True,
)
Son olarak, yukarıdaki kuralların her ikisi için de hedefler oluşturmak üzere aşağıdaki makroyu tanımlayın:
def sphinx_site(name, srcs = [], **kwargs):
# This creates the primary target, producing the Sphinx-generated HTML.
_sphinx_site(name = name, srcs = srcs, **kwargs)
# This creates the secondary target, which produces a script for publishing
# the site generated above.
_sphinx_publisher(name = "%s.publish" % name, site = name, **kwargs)
BUILD
dosyalarında makroyu yalnızca birincil hedefi oluşturuyormuş gibi kullanın:
sphinx_site(
name = "docs",
srcs = ["index.md", "providers.md"],
)
Bu örnekte, sanki makro standart, tek bir Bazel kuralıymış gibi bir "docs" hedefi oluşturulmuştur. Kural oluşturulduğunda bir yapılandırma oluşturur ve Sphinx'i çalıştırarak manuel inceleme için hazır bir HTML sitesi oluşturur. Ancak, siteyi yayınlamak için bir komut dosyası oluşturan ek bir "docs.publish" hedefi de oluşturulur. Birincil hedefin çıktısını kontrol ettikten sonra, hayali bir bazel publish
komutu gibi herkese açık olarak yayınlamak için bazel run :docs.publish
kullanabilirsiniz.
_sphinx_publisher
kuralının nasıl uygulandığı hemen anlaşılmaz. Genellikle, bunun gibi işlemler bir başlatıcı kabuk komut dosyası yazar.
Bu yöntem genellikle çok basit bir kabuk komut dosyası yazmak için ctx.actions.expand_template
kullanılmasını içerir. Bu durumda, yayıncı ikilisini birincil hedefin çıkışına giden bir yola sahip olarak çağırabilirsiniz. Bu şekilde, yayıncının uygulaması genel kalabilir, _sphinx_site
kuralı yalnızca HTML oluşturabilir ve bu küçük komut dosyası, ikisini birlikte birleştirmek için gereken tek şeydir.
rules_k8s
'te .apply
'un yaptığı tam olarak budur:
expand_template
apply.sh.tpl
'e dayalı çok basit bir Bash komut dosyası yazar, bu komut dosyası da birincil hedefin çıktısıyla kubectl
'i çalıştırır. Bu komut dosyası daha sonra bazel run :staging.apply
ile derlenip çalıştırılabilir. Böylece k8s_object
hedefleri için etkili bir k8s-apply
komutu sağlanır.