blob: 7906a36a8f43dc88ff44168be50b75dc7bbf592a [file]
"""Common rule implemenation for applying Buf plugins."""
load("@bazel_skylib//lib:shell.bzl", "shell")
load("@rules_proto//proto:defs.bzl", "ProtoInfo")
load("@rules_proto_grpc//internal:common.bzl", "descriptor_proto_path")
load("@rules_proto_grpc//internal:protoc.bzl", "build_protoc_args")
load("@rules_proto_grpc//internal:providers.bzl", "ProtoPluginInfo")
TEST_ATTRS = [
# From https://bazel.build/reference/be/common-definitions#common-attributes-tests
"args",
"env",
"env_inherit",
"size",
"timeout",
"flaky",
"shard_count",
"local",
]
def buf_test_script_impl(ctx, options):
"""
Common implementation function for buf rules.
Args:
ctx: The Bazel rule execution context object.
options: The generated options to pass to the plugins.
Returns:
Providers:
- DefaultInfo
"""
# Load toolchain
protoc_toolchain_info = ctx.toolchains[str(Label("@rules_proto_grpc//protoc:toolchain_type"))]
protoc = protoc_toolchain_info.protoc_executable
# Create test script header
script_file = ctx.actions.declare_file(ctx.label.name)
content = """#!/usr/bin/env bash
set -uo pipefail
"""
# Load providers
proto_infos = [dep[ProtoInfo] for dep in ctx.attr.protos]
plugins = [plugin[ProtoPluginInfo] for plugin in ctx.attr._plugins]
# Add a command for each plugin
plugin_executables = []
all_inputs = [ctx.file.against_input] if hasattr(ctx.file, "against_input") else []
for plugin in plugins:
# Get plugin
plugin_executables.append(plugin.tool_executable)
# Get proto paths
proto_paths = [] # The paths passed to protoc
for proto_info in proto_infos:
for proto in proto_info.direct_sources:
proto_paths.append(descriptor_proto_path(proto, proto_info))
# Build command
args_list, cmd_inputs, _ = build_protoc_args(
ctx,
plugin,
proto_infos,
".",
short_paths = True,
extra_options = options,
resolve_tools = False,
)
all_inputs += cmd_inputs
# Add source proto files as descriptor paths
for proto_path in proto_paths:
args_list.append(proto_path)
content += "{} {}\n".format(shell.quote(protoc.short_path), " ".join([shell.quote(arg) for arg in args_list]))
# Write test script
ctx.actions.write(script_file, content, is_executable = True)
return [
DefaultInfo(
runfiles = ctx.runfiles(
files = [protoc] + plugin_executables + all_inputs,
),
executable = script_file,
),
]
def buf_proto_breaking_test_script_impl(ctx):
return buf_test_script_impl(ctx, [json.encode({
"against_input": ctx.file.against_input.short_path,
"limit_to_input_files": True,
"input_config": {
"version": "v1",
"breaking": {
"use": ctx.attr.use_rules,
"except": ctx.attr.except_rules,
},
},
})])
def buf_proto_lint_test_script_impl(ctx):
return buf_test_script_impl(ctx, [json.encode({
"input_config": {
"version": "v1",
"lint": {
"use": ctx.attr.use_rules,
"except": ctx.attr.except_rules,
"enum_zero_value_suffix": ctx.attr.enum_zero_value_suffix,
"rpc_allow_same_request_response": ctx.attr.rpc_allow_same_request_response,
"rpc_allow_google_protobuf_empty_requests": ctx.attr.rpc_allow_google_protobuf_empty_requests,
"rpc_allow_google_protobuf_empty_responses": ctx.attr.rpc_allow_google_protobuf_empty_responses,
"service_suffix": ctx.attr.service_suffix,
},
},
})])