Bazel ile günlük etkileşim, temel olarak birkaç komutla gerçekleşir:
build
, test
ve run
. Ancak bazen bu seçenekler sınırlı gelebilir: Paketleri bir depoya göndermek, son kullanıcılar için dokümanlar 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 mükemmel bir araçtır. Bazel kullanıcıları, yürütülebilir dosyalar oluşturan kurallara alışkındır ve kural yazarları bunu "özel fiiller"e genişletmek için ortak bir kalıp grubunu takip edebilir.
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",
)
k8s_object
kuralı, staging
hedefinde bazel build
kullanıldığında standart bir Kubernetes YAML dosyası oluşturur. Ancak ek hedefler, k8s_object
staging.apply
ve :staging.delete
gibi adlara sahip makrolar 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, normal bir bazel
test
çağrısıyla derlenebilir ve çalıştırılabilir. angular-cli
'te, bazel test //etc/api:angular_devkit_core_api
ile böyle bir hedef çalıştırabilirsiniz.
Zaman içinde bu altın dosyanın 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öreceksiniz.
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 birlikte hedef oluşturmak üzere aşağıdaki sembolik makroyu (Bazel 8 veya daha yeni sürümlerde kullanılabilir) tanımlayın:
def _sphinx_site_impl(name, visibility, srcs, **kwargs):
# This creates the primary target, producing the Sphinx-generated HTML. We
# set `visibility = visibility` to make it visible to callers of the
# macro.
_sphinx_site(name = name, visibility = visibility, srcs = srcs, **kwargs)
# This creates the secondary target, which produces a script for publishing
# the site generated above. We don't want it to be visible to callers of
# our macro, so we omit visibility for it.
_sphinx_publisher(name = "%s.publish" % name, site = name, **kwargs)
sphinx_site = macro(
implementation = _sphinx_site_impl,
attrs = {"srcs": attr.label_list(allow_files = [".rst"])},
# Inherit common attributes like tags and testonly
inherit_attrs = "common",
)
Bazel 8'den eski Bazel sürümlerini desteklemeniz gerekiyorsa bunun yerine eski bir makro tanımlarsınız:
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, makro standart, tek bir Bazel kuralıymış gibi bir "docs" hedefi oluşturulur. Kurulduğunda kural bazı yapılandırmalar oluşturur ve manuel incelemeye hazır bir HTML sitesi oluşturmak için Sphinx'i çalıştırır. 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 uygulanmasının nasıl görüneceği hemen anlaşılmıyor. Bu tür işlemler genellikle 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 sayede yayıncı uygulaması genel kalabilir, _sphinx_site
kuralı yalnızca HTML oluşturabilir ve bu ikisini birleştirmek için gereken tek şey bu küçük komut dosyasıdır.
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.