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

Sorun bildirin Kaynağı göster

Bazel ile günlük etkileşim öncelikle birkaç komut aracılığıyla gerçekleşir: build, test ve run. Bununla birlikte, bazen bu kapasitenin kısıtlı olduğu durumlar 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 çalıştırma 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ışabilir ve her bazel build ile tekrar çalıştırılacağı garanti edilmez.

Bunun yerine, yan etkileri istediğiniz görevler için destekleyici olan bazel run'den yararlanın. 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.

Vahşi yaşam: 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",
)

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 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. Birincisi, oluşturulan bir çıktıyı "altın" dosya (yani beklenen çıkışı içeren bir dosya) ile 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 bölgesinde, 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. 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ın aynısını uygular: Yerel bir bazel test-accept komutu yoktur ancak aynı etki bazel run //etc/api:angular_devkit_core_api.accept ile de elde edilebilir.

Bu kalıp oldukça güçlü olabilir ve tanımayı öğrendiğinizde oldukça yaygın olduğu ortaya çıkar.

Kendi kurallarınızı uyarlama

Makrolar bu kalıbın temelini oluşturur. Makrolar kurallar gibi kullanılsa da birkaç hedef oluşturabilir. Genellikle, belirtilen adla birincil derleme işlemini (ör. normal bir ikili program, Docker görüntüsü veya bir kaynak kodu arşivi derleme) gerçekleştiren bir hedef oluştururlar. 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 göstermek için, Sfenks içeren bir web sitesi oluşturan sanal bir kuralı, bir makroyla sarmalayın. Böylece, kullanıcının hazır olduğunda bu kuralı yayınlamasına izin veren ek bir hedef oluşturabilirsiniz. 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, çalıştırıldığında, oluşturulan sayfaları yayınlayan bir komut dosyası oluşturan aşağıdaki gibi bir kural düşünün:

_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 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. Bununla birlikte, ek bir "docs.publish" hedefi de oluşturulur. Böylece, siteyi yayınlamak için bir komut dosyası 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_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ö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. Daha sonra bu komut dosyası, 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.