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

Sorun bildir Kaynağı görüntüleyin Nightly · 7.4 . 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'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.