%% `warn_missing_spec` (which livery enforces) is intentionally absent:
%% gpb-generated `_pb` modules do not spec their introspection functions,
%% so they cannot satisfy it. Hand-written modules carry specs and
%% dialyzer enforces types.
%%
%% Generated `*_pb` modules are kept out of every style/static check:
%% erlfmt (exclude_files), elvis (ignore regex), and xref (xref_ignores).
%% `proto/helloworld.proto` is a test fixture; a consumer application runs
%% the gpb plugin against its own protos.
{erl_opts, [debug_info, warnings_as_errors]}.
%% `livery` is declared as a dependency so it joins the build graph; the
%% local `_checkouts/livery` symlink overrides the source (no hex fetch for
%% livery itself). Its transitive deps (h1, h2, ...) are fetched from hex.
%% `gpb` is the protobuf runtime used by generated modules and the codec.
%% h2 >= 0.10.0 (within 0.10.x) is required directly, overriding livery's
%% transitive 0.9.0, for its bidirectional-streaming support: per-stream
%% event routing, send and receive backpressure, and per-stream cancel.
{deps, [
{livery, "0.3.0"},
{h2, "~> 0.10.0"},
{gpb, "5.0.0"}
]}.
%% Compile proto/*.proto -> src/*_pb.erl (maps mode) before erl compile.
{gpb_opts, [
{i, "proto"},
{module_name_suffix, "_pb"},
{o_erl, "src"},
%% Maps mode generates no .hrl, so point this at src (which always
%% exists) rather than an empty include/ dir that is absent on a fresh
%% clone and would break the build.
{o_hrl, "src"},
{strings_as_binaries, true},
{maps, true},
{maps_unset_optional, omitted},
type_specs,
%% Emit descriptor/0,1 returning the file's FileDescriptorProto bytes,
%% which the reflection service serves to clients.
descriptor,
{report_warnings, true}
]}.
{provider_hooks, [
{pre, [
{compile, {protobuf, compile}},
{clean, {protobuf, clean}}
]}
]}.
%% Generated protobuf modules carry gpb's internal helpers, some unused
%% per message set. Keep them out of xref's unused-locals analysis.
{xref_ignores, [helloworld_pb, health_pb, reflection_pb, route_guide_pb]}.
{shell, [
{apps, [livery_grpc]}
]}.
{cover_enabled, true}.
{cover_opts, [verbose]}.
{eunit_opts, [verbose]}.
{xref_checks, [
undefined_function_calls,
undefined_functions,
locals_not_used,
deprecated_function_calls,
deprecated_functions
]}.
{dialyzer, [
{warnings, [unmatched_returns, error_handling, unknown]},
{plt_extra_apps, [livery, h2, gpb, crypto, ssl, public_key]}
]}.
{project_plugins, [
{erlfmt, "1.7.0"},
{rebar3_lint, "4.1.1"},
{rebar3_gpb_plugin, "3.0.1"},
rebar3_ex_doc
]}.
{erlfmt, [
write,
{files, [
"{src,include,test,examples}/**/*.{hrl,erl,app.src}",
"rebar.config"
]},
%% Generated protobuf modules are not hand-edited.
{exclude_files, ["src/*_pb.erl", "include/*_pb.hrl"]}
]}.
{ex_doc, [
{source_url, <<"https://github.com/benoitc/livery_grpc">>},
{main, <<"readme">>},
{extras, [
{"README.md", #{title => <<"Overview">>}},
{"docs/overview.md", #{title => <<"Introduction">>}},
{"docs/core-concepts.md", #{title => <<"Core concepts">>}},
{"docs/getting-started.md", #{title => <<"Getting started">>}},
{"docs/basics-tutorial.md", #{title => <<"Basics tutorial">>}},
{"docs/guides/streaming.md", #{title => <<"Streaming">>}},
{"docs/guides/metadata.md", #{title => <<"Metadata">>}},
{"docs/guides/interceptors.md", #{title => <<"Interceptors">>}},
{"docs/guides/deadlines.md", #{title => <<"Deadlines">>}},
{"docs/guides/cancellation.md", #{title => <<"Cancellation">>}},
{"docs/guides/error-handling.md", #{title => <<"Error handling">>}},
{"docs/guides/status-codes.md", #{title => <<"Status codes">>}},
{"docs/guides/compression.md", #{title => <<"Compression">>}},
{"docs/guides/authentication.md", #{title => <<"Authentication">>}},
{"docs/guides/health-checking.md", #{title => <<"Health checking">>}},
{"docs/guides/reflection.md", #{title => <<"Reflection">>}},
{"docs/guides/retry.md", #{title => <<"Retry">>}},
{"docs/guides/graceful-shutdown.md", #{title => <<"Graceful shutdown">>}},
{"docs/guides/flow-control.md", #{title => <<"Flow control">>}},
{"docs/guides/wait-for-ready.md", #{title => <<"Wait for ready">>}},
{"docs/guides/grpc-web.md", #{title => <<"gRPC-Web">>}},
{"docs/guides/generated-stubs.md", #{title => <<"Generated stubs">>}},
{"docs/guides/erlang-integration.md", #{title => <<"Integrate into an Erlang app">>}},
{"docs/guides/testing.md", #{title => <<"Testing">>}},
{"docs/design.md", #{title => <<"Design">>}},
{"CHANGELOG.md", #{title => <<"Changelog">>}}
]},
{groups_for_extras, [
{<<"Start here">>, [
<<"docs/overview.md">>,
<<"docs/core-concepts.md">>,
<<"docs/getting-started.md">>
]},
{<<"Tutorial">>, [<<"docs/basics-tutorial.md">>]},
{<<"Guides">>, [
<<"docs/guides/streaming.md">>,
<<"docs/guides/metadata.md">>,
<<"docs/guides/interceptors.md">>,
<<"docs/guides/deadlines.md">>,
<<"docs/guides/cancellation.md">>,
<<"docs/guides/error-handling.md">>,
<<"docs/guides/status-codes.md">>,
<<"docs/guides/compression.md">>,
<<"docs/guides/authentication.md">>,
<<"docs/guides/health-checking.md">>,
<<"docs/guides/reflection.md">>,
<<"docs/guides/retry.md">>,
<<"docs/guides/graceful-shutdown.md">>,
<<"docs/guides/flow-control.md">>,
<<"docs/guides/wait-for-ready.md">>,
<<"docs/guides/grpc-web.md">>,
<<"docs/guides/generated-stubs.md">>,
<<"docs/guides/erlang-integration.md">>,
<<"docs/guides/testing.md">>
]},
{<<"Design">>, [<<"docs/design.md">>]},
{<<"Project">>, [<<"CHANGELOG.md">>]}
]},
{groups_for_modules, [
{<<"Server and client">>, [livery_grpc, livery_grpc_server, livery_grpc_client]},
{<<"Streaming and codegen">>, [
livery_grpc_stream, livery_grpc_service, livery_grpc_codegen
]},
{<<"Built-in services">>, [livery_grpc_reflection, livery_grpc_health]},
{<<"Wire format">>, [
livery_grpc_wire,
livery_grpc_frame,
livery_grpc_codec,
livery_grpc_compression,
livery_grpc_status,
livery_grpc_timeout,
livery_grpc_web
]},
{<<"Runtime">>, [livery_grpc_app, livery_grpc_sup, livery_grpc_health_store]}
]}
]}.
{hex, [{doc, #{provider => ex_doc}}]}.
{elvis, [
#{
dirs => ["src"],
filter => "*.erl",
%% Generated protobuf modules (`*_pb.erl`) are not linted. elvis
%% matches this regex against the file path.
ignore => ["_pb\\.erl$"],
rules => [
{elvis_style, no_macros, disable},
{elvis_style, no_common_caveats_call, disable},
{elvis_style, no_init_lists, disable},
{elvis_style, param_pattern_matching, disable},
%% The health Watch relay blocks on receive until a status
%% change or the client disconnect; an after clause is wrong.
{elvis_style, no_receive_without_timeout, #{ignore => [livery_grpc_health]}},
%% gen_server using a bare #state{} record, as livery does for
%% its own gen_servers.
{elvis_style, state_record_and_type, #{
ignore => [livery_grpc_health_store, livery_grpc_listener]
}},
{elvis_style, no_spec_with_records, #{ignore => [livery_grpc_health_store]}},
%% These dispatch to the gpb-generated proto module by design
%% (Mod:encode_msg, Proto:get_service_def, ...).
{elvis_style, invalid_dynamic_call, #{
ignore => [
livery_grpc_codec,
livery_grpc_service,
livery_grpc_server,
livery_grpc_client,
livery_grpc_reflection,
livery_grpc_codegen
]
}}
],
ruleset => erl_files_strict
},
#{
dirs => ["."],
filter => "rebar.config",
rules => [
{elvis_project, no_branch_deps, disable}
],
ruleset => rebar_config
}
]}.
{profiles, [
{test, [
{erl_opts, [debug_info, nowarn_export_all, nowarn_missing_spec]},
{deps, [{proper, "1.4.0"}]},
%% Compile examples/ in the test profile so the example modules
%% (route_guide, greeter_example) can be exercised by tests.
{extra_src_dirs, [{"examples", [{recursive, false}]}]}
]},
{examples, [
{extra_src_dirs, [{"examples", [{recursive, false}]}]},
{erl_opts, [debug_info, nowarn_missing_spec]}
]}
]}.