Bazel ile günlük etkileşim genellikle şu birkaç komut aracılığıyla gerçekleşir:
build
, test
ve run
. Ancak bazen bu özellikler sınırlı kalabilir. Örneğin, paketleri bir depoya göndermek, son kullanıcılar için doküman yayınlamak veya Kubernetes ile bir uygulama dağıtmak isteyebilirsiniz. Ancak Bazel'de publish
veya deploy
komutu yok. Bu işlemler nereye sığar?
bazel run komutu
Bazel'in hermetiklik, tekrarlanabilirlik ve artımlılık üzerine odaklanması nedeniyle build
ve test
komutları yukarıdaki görevler için yararlı değildir. Bu işlemler, sınırlı ağ erişimiyle bir korumalı alanda çalışabilir ve her bazel build
ile yeniden çalıştırılacağı garanti edilmez.
Bunun yerine, yan etkileri olmasını istediğiniz görevler için bazel run
kullanın. Bazel kullanıcıları, yürütülebilir dosyalar oluşturan kurallara alışkındır ve kural yazarları, bunu "özel fiillere" genişletmek için ortak bir dizi kalıbı takip edebilir.
Doğada: rules_k8s
Örneğin, Bazel için Kubernetes kurallarını (rules_k8s
) ele alalım. Aşağıdaki hedefiniz olduğunu 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 de k8s_object
makrosu tarafından staging.apply
ve :staging.delete
gibi adlarla oluşturulur. Bu komutlar, söz konusu işlemleri gerçekleştirmek için derleme komut dosyaları oluşturur ve bazel run
staging.apply
ile yürütüldüğünde 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. Birincisi, 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 oluşturulup çalıştırılabilir. angular-cli
bölgesinde bazel test //etc/api:angular_devkit_core_api
ile bu tür bir hedef çalıştırabilirsiniz.
Bu altın dosya, zaman içinde meşru nedenlerle güncellenmesi gerekebilir.
Bunu manuel olarak güncellemek sıkıcı ve hataya açık bir işlem olduğundan bu makro, altın dosyayla karşılaştırmak yerine dosyayı güncelleyen bir nodejs_binary
hedefi de sağlar. Aynı test komut dosyası, nasıl çağrıldığına bağlı olarak "doğrula" veya "kabul et" modunda çalışacak şekilde yazılabilir. Bu, daha önce öğrendiğinizle aynı kalıbı izler: Yerel 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 etkili olabilir ve onu tanımayı öğrendiğinizde oldukça yaygın olduğunu fark edersiniz.
Kendi kurallarınızı uyarlama
Bu kalıbın temelinde makrolar yer alır. Makrolar kurallar gibi kullanılır ancak birden fazla hedef oluşturabilirler. Genellikle, birincil derleme işlemini gerçekleştiren, belirtilen ada sahip bir hedef oluştururlar: Belki normal bir ikili dosya, bir Docker görüntüsü veya kaynak kodu arşivi oluşturur. Bu düzende, birincil hedefin çıktısına göre yan etkiler gerçekleştiren komut dosyaları oluşturmak için ek hedefler oluşturulur. Örneğin, ortaya çıkan ikili dosyayı yayınlama veya beklenen test çıktısını güncelleme gibi.
Bunu göstermek için, Sphinx ile web sitesi oluşturan hayali bir kuralı, kullanıcı hazır olduğunda yayınlamasına olanak tanıyan ek bir hedef oluşturmak üzere 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ı göz önünde bulundurun. 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 iki kural için de birlikte hedefler 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",
)
Alternatif olarak, Bazel 8'den eski Bazel sürümlerini desteklemeniz gerekiyorsa bunun yerine eski bir makro tanımlayabilirsiniz:
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 bir tek Bazel kuralıymış gibi bir "docs" hedefi oluşturulur. Kural oluşturulduğunda bazı yapılandırmalar oluşturur ve Sphinx'i çalıştırarak manuel incelemeye 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 çıkışını kontrol ettikten sonra, bazel run :docs.publish
komutunu kullanarak herkese açık tüketim için yayınlayabilirsiniz. Bu, hayali bir bazel publish
komutuna benzer.
_sphinx_publisher
kuralının nasıl uygulanacağı hemen anlaşılmayabilir. Genellikle bu tür işlemler başlatıcı kabuk komut dosyası yazar.
Bu yöntemde genellikle ctx.actions.expand_template
kullanılarak çok basit bir kabuk komut dosyası yazılır. Bu durumda, yayıncı ikili dosyası birincil hedefin çıktısının yoluyla çağrılır. Bu sayede yayıncı uygulaması genel kalabilir, _sphinx_site
kuralı yalnızca HTML oluşturabilir ve ikisini birleştirmek için bu küçük komut dosyası yeterli olur.
rules_k8s
'da .apply
gerçekten de bunu yapar:
expand_template
apply.sh.tpl
'a dayalı çok basit bir Bash komut dosyası yazar ve bu komut dosyası, birincil hedefin çıkışıyla kubectl
'ı çalıştırır. Bu komut dosyası daha sonra bazel run :staging.apply
ile oluşturulup çalıştırılabilir ve k8s_object
hedefleri için etkili bir k8s-apply
komutu sağlar.