Özel Fiiller Oluşturmak için Makroları Kullanma

7.3 · 7.2 · 7.1 · 7.0 · 6.5

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'ın publish veya deploy komutu yok. Bu işlemler nerede gerçekleşir?

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şimiyle bir korumalı alanda çalıştırılabilir ve her bazel build ile tekrar çalıştırılacağı 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 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'in Kubernetes kuralları olan rules_k8s'i 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_objectstaging.apply ve :staging.delete gibi adlara sahip makrolar tarafından da oluşturulur. Bu işlemleri gerçekleştirmek için kullanılan derleme komut dosyaları ve bazel run staging.apply ile yürütüldüğünde bunlar 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.

Zaman içinde bu altın dosyanın geçerli nedenlerle güncellenmesi gerekebilir. Bunun manuel olarak güncellenmesi yorucu ve hataya açık olduğundan bu makro, karşılaştırma yerine altın dosyayı güncelleyen bir nodejs_binary hedefi de sağlar. Aynı test komut dosyası, çağrılma şekline bağlı olarak "doğrulama" veya "kabul etme" 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

Makrolar bu kalıbın temelini oluşturur. 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, elde edilen ikili programı yayınlama veya beklenen test çıkışını güncelleme gibi birincil hedefin çıkışına göre yan etkiler yapan komut dosyaları oluşturmak için ek hedefler oluşturulur.

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. Sfenks içeren bir 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, makro standart, tek bir Bazel kuralıymış gibi bir "docs" hedefi oluşturulur. Kural oluşturulduğunda 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 çıkışını kontrol ettikten sonra, bazel run :docs.publish kullanarak sanal bir bazel publish komutu gibi herkesin kullanımına açık şekilde yayınlayabilirsiniz.

_sphinx_publisherKuralının uygulanmasının nasıl görüneceği hemen anlaşılmıyor. Genellikle, bunun gibi işlemler bir başlatıcı kabuk komut dosyası yazar. Bu yöntemde genellikle çok basit bir kabuk komut dosyası yazmak için ctx.actions.expand_template kullanılması gerekir. Bu örnekte, yayıncı ikili programı, birincil hedefin çıkışına giden bir yol ile birlikte çağrılır. 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 ürününde .apply, tam olarak bunu yapar: expand_template, birincil hedefin çıkışıyla kubectl çalıştıran apply.sh.tpl öğesine dayalı olarak çok basit bir Bash komut dosyası yazar. 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.