Hoạt động tương tác hằng ngày với Bazel chủ yếu diễn ra thông qua một số lệnh:
build
, test
và run
. Mặc dù vậy, đôi khi những yếu tố này có giới hạn: bạn có thể
muốn đẩy các gói vào một kho lưu trữ, xuất bản tài liệu cho người dùng cuối, hoặc
triển khai ứng dụng bằng Kubernetes. Nhưng Bazel không có publish
hoặc
Lệnh deploy
– những thao tác này phù hợp ở đâu?
Lệnh chạy bazel
Bazel chú trọng vào tính ẩn giấu, khả năng tái tạo và gia tăng
Các lệnh build
và test
không hữu ích cho những nhiệm vụ trên. Các hành động này
có thể chạy trong một hộp cát, có quyền truy cập mạng bị giới hạn và không được đảm bảo là
chạy lại với mỗi bazel build
.
Thay vào đó, hãy dựa vào bazel run
: quy trình làm việc cho các tác vụ mà bạn muốn có
các tác dụng phụ. Người dùng Bazel đã quen thuộc với các quy tắc tạo tệp thực thi, và
người tạo quy tắc có thể làm theo một nhóm mẫu phổ biến để mở rộng quy tắc này
"động từ tuỳ chỉnh".
Trong tự nhiên: rules_k8s
Ví dụ: hãy xem xét rules_k8s
,
các quy tắc của Kubernetes đối với Bazel. Giả sử bạn có mục tiêu sau đây:
# BUILD file in //application/k8s
k8s_object(
name = "staging",
kind = "deployment",
cluster = "testing",
template = "deployment.yaml",
)
Quy tắc k8s_object
tạo
tệp YAML của Kubernetes khi sử dụng bazel build
trên staging
. Tuy nhiên, các mục tiêu khác cũng được k8s_object
tạo
có các tên như staging.apply
và :staging.delete
. Bản dựng này
để thực hiện những hành động đó và khi được thực thi bằng bazel run
staging.apply
, các tập lệnh này sẽ hoạt động giống như lệnh bazel k8s-apply
hoặc bazel
k8s-delete
của chúng ta.
Ví dụ khác: ts_api_guardian_test
Mẫu này cũng có thể xem được trong dự án Angular. Chiến lược phát hành đĩa đơn
Macro ts_api_guardian_test
tạo ra hai mục tiêu. Mục tiêu đầu tiên là mục tiêu nodejs_test
chuẩn để so sánh
một số đầu ra được tạo dựa trên "vàng" (tức là một tệp chứa
kết quả dự kiến). Bạn có thể tạo và chạy ứng dụng này bằng lệnh gọi bazel
test
thông thường. Trong angular-cli
, bạn có thể chạy một như vậy
mục tiêu
cùng với bazel test //etc/api:angular_devkit_core_api
.
Theo thời gian, chúng tôi có thể cần cập nhật tệp quan trọng này vì các lý do chính đáng.
Việc cập nhật thủ công này rất tẻ nhạt và dễ xảy ra lỗi, vì vậy macro này cũng cung cấp
mục tiêu nodejs_binary
cập nhật tệp Golden, thay vì so sánh
dựa vào nội dung đó. Trên thực tế, bạn có thể viết cùng một tập lệnh kiểm thử để chạy trong tuỳ chọn "xác minh"
hoặc "chấp nhận" dựa vào cách gọi được gọi. Việc này tuân theo cùng một mẫu
mà bạn đã biết: không có lệnh bazel test-accept
gốc, nhưng
có thể đạt được hiệu quả tương tự với
bazel run //etc/api:angular_devkit_core_api.accept
Mẫu này có thể khá mạnh mẽ và trở nên khá phổ biến khi bạn học cách nhận ra thương hiệu đó.
Điều chỉnh các quy tắc của riêng bạn
Macro là thành phần chính của mẫu này. Macro được sử dụng như nhưng chúng có thể tạo một vài mục tiêu. Thông thường, chúng sẽ tạo một mục tiêu có tên được chỉ định thực hiện hành động tạo chính: có thể nó sẽ tạo một tệp nhị phân thông thường, một hình ảnh Docker hoặc một kho lưu trữ mã nguồn. Trong mẫu này, các mục tiêu khác sẽ được tạo để tạo ra khía cạnh hoạt động của tập lệnh những tác động dựa trên kết quả của mục tiêu chính, chẳng hạn như xuất bản tệp nhị phân hoặc cập nhật kết quả đầu ra kiểm thử dự kiến.
Để minh hoạ điều này, hãy gói một quy tắc ảo tạo ra một trang web Sphinx với macro để tạo thêm cho phép người dùng xuất bản khi đã sẵn sàng. Hãy cân nhắc những điều sau quy tắc hiện tại để tạo trang web bằng Sphinx:
_sphinx_site = rule(
implementation = _sphinx_impl,
attrs = {"srcs": attr.label_list(allow_files = [".rst"])},
)
Tiếp theo, hãy xem xét quy tắc như sau. Quy tắc này sẽ tạo tập lệnh mà khi chạy xuất bản các trang đã tạo:
_sphinx_publisher = rule(
implementation = _publish_impl,
attrs = {
"site": attr.label(),
"_publisher": attr.label(
default = "//internal/sphinx:publisher",
executable = True,
),
},
executable = True,
)
Cuối cùng, xác định macro sau đây để tạo mục tiêu cho cả hai hoạt động trên quy tắc kết hợp:
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)
Trong các tệp BUILD
, hãy dùng macro như thể macro này chỉ tạo
mục tiêu:
sphinx_site(
name = "docs",
srcs = ["index.md", "providers.md"],
)
Trong ví dụ này là "tài liệu" được tạo, giống như macro là
quy tắc Bazel chuẩn và duy nhất. Khi được tạo, quy tắc này sẽ tạo ra một số cấu hình
và chạy Sphinx để tạo một trang web HTML, sẵn sàng cho việc kiểm tra thủ công. Tuy nhiên,
tệp "docs.publish" bổ sung nhắm mục tiêu cũng được tạo. Thao tác này sẽ tạo tập lệnh cho
xuất bản trang web. Sau khi kiểm tra kết quả của mục tiêu chính, bạn có thể
sử dụng bazel run :docs.publish
để xuất bản để công khai, tương tự như
một lệnh bazel publish
giả tưởng.
Không thể nhận thấy ngay việc triển khai _sphinx_publisher
có thể trông giống như thế nào. Thông thường, các thao tác như thế này sẽ ghi tập lệnh shell trình chạy.
Phương pháp này thường bao gồm việc sử dụng
ctx.actions.expand_template
để viết một tập lệnh shell rất đơn giản, trong trường hợp này gọi tệp nhị phân của nhà xuất bản
có một đường dẫn đến đầu ra của mục tiêu chính. Bằng cách này, nhà xuất bản
Phương thức triển khai vẫn có thể chung chung, quy tắc _sphinx_site
chỉ có thể tạo
HTML và tập lệnh nhỏ này là tất cả những gì cần thiết để kết hợp cả hai
khi kết hợp cùng nhau.
Trong rules_k8s
, đây thực sự là những gì .apply
thực hiện:
expand_template
viết một tập lệnh Bash rất đơn giản, dựa trên
apply.sh.tpl
,
chạy kubectl
với dữ liệu đầu ra của mục tiêu chính. Tập lệnh này có thể
sau đó tạo và chạy bằng bazel run :staging.apply
, cung cấp một cách hiệu quả
Lệnh k8s-apply
cho các mục tiêu k8s_object
.