매크로를 사용하여 커스텀 동사 만들기

문제 신고 <ph type="x-smartling-placeholder"></ph> 소스 보기 1박 · 7.2 · 7.1 · 7.0 · 6.5 · 6.4

Bazel과의 일상적인 상호작용은 주로 다음과 같은 몇 가지 명령을 통해서 이루어집니다. build, test, run 하지만 때때로 이러한 제약이 있다고 느낄 수 있습니다. 패키지를 저장소로 푸시하거나, 최종 사용자를 위한 문서를 게시하거나, Kubernetes로 애플리케이션을 배포하는 방법을 알아봅니다 하지만 Bazel에는 publish 또는 deploy 명령어: 이러한 작업은 어디에 적합한가요?

bazel 실행 명령어

밀폐성, 재현성, 성과 증분에 중점을 두는 Bazel은 buildtest 명령어는 위 작업에 유용하지 않습니다. 이러한 작업 네트워크 액세스가 제한된 샌드박스에서 실행될 수 있으며 bazel build마다 재실행됩니다.

대신 원하는 작업을 위한 주체인 bazel run를 사용하세요. 부작용이 있을 수 있습니다 Bazel 사용자는 실행 파일을 만드는 규칙에 익숙하며 규칙 작성자는 일반적인 패턴에 따라 이를 확장하여 'custom verbs'가 있습니다.

실제 상황에서: rules_k8s

예를 들어 rules_k8s를 살펴보겠습니다. Bazel용 Kubernetes 규칙입니다 다음과 같은 타겟이 있다고 가정해 보겠습니다.

# BUILD file in //application/k8s
k8s_object(
    name = "staging",
    kind = "deployment",
    cluster = "testing",
    template = "deployment.yaml",
)

k8s_object 규칙bazel buildstaging에서 사용되는 경우 표준 Kubernetes YAML 파일 있습니다. 그러나 추가 타겟도 k8s_object에 의해 생성됩니다. 매크로를 staging.apply:staging.delete과 같은 이름으로 사용합니다. 이러한 빌드는 스크립트를 사용하여 이러한 작업을 실행하고, bazel run staging.apply로 실행하면 자체 bazel k8s-apply 또는 bazel k8s-delete 명령어처럼 동작합니다.

다른 예: ts_api_guardian_test

이 패턴은 Angular 프로젝트에서도 볼 수 있습니다. 이 ts_api_guardian_test 매크로 두 개의 타겟을 생성합니다. 첫 번째는 표준 nodejs_test 타겟으로 출력은 'golden'에 대해 파일 (즉, 예상 출력). 이는 일반적인 bazel test 호출로 빌드하고 실행할 수 있습니다. angular-cli에서는 이러한 대상 bazel test //etc/api:angular_devkit_core_api.

시간이 지남에 따라 타당한 이유로 이 골든 파일을 업데이트해야 할 수도 있습니다. 이 매크로를 수동으로 업데이트하는 것은 지루하고 오류가 발생하기 쉬우므로, 이 매크로는 골든 파일을 업데이트하는 nodejs_binary 타겟 맞서 싸웁니다. 실질적으로 동일한 테스트 스크립트를 작성하여 'verify'에서 실행할 수 있습니다. 또는 '동의' 호출 방식에 따라 달라집니다. 이것은 동일한 패턴을 따릅니다. 네이티브 bazel test-accept 명령어는 없지만 동일한 효과를 얻을 수 있습니다. bazel run //etc/api:angular_devkit_core_api.accept입니다.

이 패턴은 매우 강력할 수 있지만, 그것을 인식하는 법을 배우게 됩니다.

자체 규칙 조정

매크로는 이 패턴의 핵심입니다. 매크로는 여러 대상을 만들 수 있습니다. 일반적으로 포드는 기본 빌드 작업을 수행하는 지정된 이름을 가진 대상(예: 일반 바이너리, Docker 이미지 또는 소스 코드의 아카이브를 빌드합니다. 포함 추가 타겟이 생성되어 성능 측면의 스크립트를 생성합니다. 기본 대상의 출력에 기초한 영향을 미칩니다. 테스트 출력을 업데이트할 수 있습니다.

이를 설명하기 위해 웹사이트를 생성하는 가상의 규칙을 Sphinx를 매크로가 있는 사용할 준비가 되면 사용자가 게시할 수 있도록 허용하는 대상입니다. 다음 사항을 고려하세요. 다음 규칙을 따르세요.

_sphinx_site = rule(
     implementation = _sphinx_impl,
     attrs = {"srcs": attr.label_list(allow_files = [".rst"])},
)

다음으로, 실행 시 생성된 페이지를 게시합니다.

_sphinx_publisher = rule(
    implementation = _publish_impl,
    attrs = {
        "site": attr.label(),
        "_publisher": attr.label(
            default = "//internal/sphinx:publisher",
            executable = True,
        ),
    },
    executable = True,
)

마지막으로 다음 매크로를 정의하여 위의 두 가지 모두에 대한 타겟을 만듭니다. 함께 사용할 수 있습니다.

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 파일에서 기본 타겟:

sphinx_site(
    name = "docs",
    srcs = ["index.md", "providers.md"],
)

이 예에서 'docs'는 매크로가 생성된 것과 마찬가지로 표준, 단일 Bazel 규칙으로 구성되어 있습니다. 작성되면 규칙은 구성을 생성함 Sphinx를 실행하여 수동 검사가 가능한 HTML 사이트를 만듭니다. 하지만 추가 'docs.publish' 대상도 생성되어 사이트를 게시하는 것입니다. 기본 대상의 출력을 확인하면 다음과 같이 bazel run :docs.publish를 사용하여 공개적으로 사용할 수 있도록 게시합니다. 가상의 bazel publish 명령어입니다.

_sphinx_publisher의 구현이 무엇을 하는지는 즉시 명확하지 않습니다. 확인할 수 있습니다. 이와 같은 작업은 런처 셸 스크립트를 작성하는 경우가 많습니다. 이 방법은 일반적으로 ctx.actions.expand_template 드림 를 사용하여 매우 간단한 셸 스크립트를 작성합니다. 이 경우 게시자 바이너리를 호출하여 기본 대상의 출력에 대한 경로를 사용합니다. 이렇게 하면 게시자가 구현은 일반 상태로 유지될 수 있지만 _sphinx_site 규칙은 이 작은 스크립트만 있으면 있습니다.

rules_k8s에서 다음은 실제로 .apply의 역할입니다. expand_template 간단한 Bash 스크립트를 작성하는 apply.sh.tpl, 이 명령어는 기본 타겟의 출력으로 kubectl를 실행합니다. 이 스크립트는 그런 다음 bazel run :staging.apply를 사용하여 빌드하고 실행하여 k8s_object 대상에 대한 k8s-apply 명령어