defmodule GrpcReflection.MixProject do use Mix.Project @version "0.5.0" @source_url "https://github.com/elixir-grpc/grpc-reflection" @description "gRPC reflection server for Elixir" def project do [ app: :grpc_reflection, version: @version, description: @description, elixir: "~> 1.15", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, deps: deps(), package: package(), docs: docs(), aliases: aliases(), test_coverage: [ ignore_modules: [ ~r/^Grpc\./, ~r/^Google\./, ~r/^ScalarTypes\./, ~r/^Streaming\./, ~r/^EmptyService\./, ~r/^EdgeCases\./, ~r/^Proto2Features\./, ~r/^CustomizedPrefix\./, ~r/^ImportsTest\./, ~r/^CommonTypes\./, ~r/^GlobalService$/, ~r/^GlobalRequest$/, ~r/^GlobalResponse$/, ~r/^Nested\./, ~r/^WellKnownTypes\./, ~r/^PackageA\./, ~r/^PackageB\./, ~r/^NestedEnumConflict\./, ~r/^RecursiveMessage\./, ~r/^NoDescriptor\./, GrpcReflection.TestEndpoint, GrpcReflection.TestEndpoint.Endpoint ] ], dialyzer: dialyzer() ] end # Run "mix help compile.app" to learn about applications. def application do [ extra_applications: [:logger] ] end # Run "mix help deps" to learn about dependencies. defp deps do [ {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:grpc, "~> 1.0"}, {:grpc_server, "~> 1.0"}, # grpc 1.0 made the HTTP client adapters optional; the test suite connects # real stubs to the in-process server, so it needs an adapter (Gun). {:gun, "~> 2.0", only: :test}, {:protobuf, "~> 0.17"} ] end defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] defp aliases do [ build_protos: [&build_protos/1], check: ["dialyzer", "credo --strict"] ] end @protoc_opts "gen_descriptors=true,gen_proto_source=true,paths=source_relative,plugins=grpc" @protoc_opts_no_descriptor "package_prefix=NoDescriptor,gen_proto_source=true,paths=source_relative,plugins=grpc" # Protos that set (elixirpb.file).module_prefix must be skipped here: that option # overrides package_prefix entirely, so the no-descriptor pass would emit modules with # the same name as the descriptor pass, causing a compile-time conflict. # Add any proto that uses the elixirpb.file module_prefix option to this list. @skip_no_descriptor ["custom_prefix_service.proto"] defp build_protos(_argv) do {reflection, fixtures} = "./priv/protos/**/*.proto" |> Path.wildcard() |> Enum.split_with(&String.contains?(&1, "reflection.proto")) # compile reflection protos cmds = reflection |> Enum.map(fn reflection_proto -> # protoc now grabs the path to the file and includes it with # the message name, which for us leads to bad paths i_path = reflection_proto |> Path.split() |> List.delete_at(-1) |> Path.join() "protoc --elixir_out=#{@protoc_opts}:./lib/proto -I=#{i_path} #{reflection_proto}" end) # compile test protos — once with descriptors, once without fixtures |> Enum.flat_map(fn proto -> i_path = proto |> Path.split() |> List.delete_at(-1) |> Path.join() with_descriptors = "protoc --elixir_out=#{@protoc_opts}:./test/support/protos -I=#{i_path} -I priv/protos -I deps/protobuf/src #{proto}" without_descriptors = "protoc --elixir_out=#{@protoc_opts_no_descriptor}:./test/support/protos -I=#{i_path} -I priv/protos -I deps/protobuf/src #{proto}" if Enum.any?(@skip_no_descriptor, &String.contains?(proto, &1)) do [with_descriptors] else [with_descriptors, without_descriptors] end end) |> Enum.concat(cmds) |> Task.async_stream(&Mix.shell().cmd(&1)) |> Enum.to_list() end defp package do %{ name: "grpc_reflection", files: ~w(.formatter.exs mix.exs lib), links: %{"GitHub" => @source_url}, licenses: ["Apache-2.0"] } end defp docs do [ extras: [ "README.md": [title: "Overview"] ], main: "readme", source_url: @source_url, source_ref: "#{@version}", formatters: ["html"] ] end defp dialyzer do [ plt_local_path: "priv/plts/project", plt_core_path: "priv/plts/core", plt_add_apps: [:ex_unit], list_unused_filters: true ] end end