From e506ce3e419205b13b715b4985456ab794c77dd0 Mon Sep 17 00:00:00 2001 From: Michael Heilmann Date: Tue, 5 May 2026 18:20:01 -0400 Subject: [PATCH] bump version number and changelog for 0.4.0 release --- CHANGELOG.md | 12 ++++++++++++ README.md | 14 +++++++++----- mix.exs | 2 +- mix.lock | 4 ++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c12cbc..2aa4632 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # CHANGELOG +## v0.4.0 (2026-05-05) + +### Enhancements + +- Add descriptor synthesizer as a fallback for services compiled without `use GRPC.Server, descriptor?: true` — reflection now works even when no file descriptor is present (#84) +- Add support for recursive message types, preventing infinite loops during symbol resolution (#82) +- Improve resolution of deeply nested message types (#83) + +### Internal + +- Overhaul test suite with representative `.proto` definitions and generated `.pb.ex` fixtures, replacing ad-hoc test services with a comprehensive set of cases covering scalar types, well-known types, streaming, imports, cross-package refs, proto2 features, edge cases, and more (#72) + ## v0.3.3 (2026-04-13) Move debug log from `info` to `debug` log levels diff --git a/README.md b/README.md index 6f87dab..bce0e76 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,12 @@ [![License](https://img.shields.io/hexpm/l/grpc_reflection.svg)](https://github.com/elixir-grpc/grpc-reflection/blob/main/LICENSE) [![Total Downloads](https://img.shields.io/hexpm/dt/grpc_reflection.svg)](https://hex.pm/packages/grpc_reflection) -Server reflection allows servers to assist clients in runtime construction of requests without having stub information precompiled into the client. +Server reflection is a mechanism that allows servers to assist clients in runtime construction of requests by informing the client directly at runtime. No pre-shared schema is required. According to the [GRPC Server Reflection Protocol ](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md), the primary usecase for server reflection is to write (typically) command line debugging tools for talking to a grpc server. In particular, such a tool will take in a method and a payload (in human readable text format) send it to the server (typically in binary proto wire format), and then take the response and decode it to text to present to the user. -GrpcReflection adds reflection support to applications built with [grpc-elixir](https://hex.pm/packages/grpc). It is a supervised application that can be implemented as a gRPC server using [grpc-elixir](https://github.com/elixir-grpc/grpc). +The GrpcReflection library adds reflection support to applications built with [grpc-elixir](https://hex.pm/packages/grpc). ## Installation @@ -31,7 +31,11 @@ This is written and tested using [grpcurl](https://github.com/fullstorydev/grpcu ## Enable reflection on your application -1. Rebuild your protos with descriptors enabled. Each module and/or service that you would like to expose through reflection must use the protoc elixir-out option `gen_descriptors=true`. +1. Ensure your protos are available using one of these options: + + - **Recommended:** expose descriptors from your proto files using the protoc elixir-out option `gen_descriptors=true`, rebuild your protos with this option and note if it is present in your `.pb.ex` file + + - **Experimental:** GrpcReflection will synthesize reflection data by introspecting your service and messages — no recompile or option needed. 1. Create a reflection server @@ -48,8 +52,8 @@ This is written and tested using [grpcurl](https://github.com/fullstorydev/grpcu | `version` | Either `:v1` or `:v1alpha`, depending on intended client support. | | `services` | This is a list of GRPC services that should be included for reflection. | - > [!NOTE] - > Multiple services are combined into a single reflection state. If fully-qualified symbol names collide for different payloads in those different services, one of the symbols could be overwritten by the other. The Builder tries to detect this and raise on collision + > #### Note {: .info} + > Multiple services are combined into a single reflection state. If fully-qualified symbol names collide across services, the Builder will raise at startup. 1. Add the reflection supervisor to your supervision tree to host the cached reflection state diff --git a/mix.exs b/mix.exs index 0e7d67f..7c76088 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule GrpcReflection.MixProject do use Mix.Project - @version "0.3.3" + @version "0.4.0" @source_url "https://github.com/elixir-grpc/grpc-reflection" @description "gRPC reflection server for Elixir" diff --git a/mix.lock b/mix.lock index 1e122e1..5ea1c49 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,7 @@ "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "cowboy": {:hex, :cowboy, "2.14.2", "4008be1df6ade45e4f2a4e9e2d22b36d0b5aba4e20b0a0d7049e28d124e34847", [:make, :rebar3], [{:cowlib, ">= 2.16.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "569081da046e7b41b5df36aa359be71a0c8874e5b9cff6f747073fc57baf1ab9"}, "cowlib": {:hex, :cowlib, "2.16.0", "54592074ebbbb92ee4746c8a8846e5605052f29309d3a873468d76cdf932076f", [:make, :rebar3], [], "hexpm", "7f478d80d66b747344f0ea7708c187645cfcc08b11aa424632f78e25bf05db51"}, - "credo": {:hex, :credo, "1.7.17", "f92b6aa5b26301eaa5a35e4d48ebf5aa1e7094ac00ae38f87086c562caf8a22f", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1eb5645c835f0b6c9b5410f94b5a185057bcf6d62a9c2b476da971cde8749645"}, + "credo": {:hex, :credo, "1.7.18", "5c5596bf7aedf9c8c227f13272ac499fe8eae6237bd326f2f07dfc173786f042", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "a189d164685fd945809e862fe76a7420c4398fa288d76257662aecb909d6b3e5"}, "dialyxir": {:hex, :dialyxir, "1.4.7", "dda948fcee52962e4b6c5b4b16b2d8fa7d50d8645bbae8b8685c3f9ecb7f5f4d", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b34527202e6eb8cee198efec110996c25c5898f43a4094df157f8d28f27d9efe"}, "earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"}, "erlex": {:hex, :erlex, "0.2.8", "cd8116f20f3c0afe376d1e8d1f0ae2452337729f68be016ea544a72f767d9c12", [:mix], [], "hexpm", "9d66ff9fedf69e49dc3fd12831e12a8a37b76f8651dd21cd45fcf5561a8a7590"}, @@ -14,7 +14,7 @@ "grpc": {:hex, :grpc, "0.11.5", "5dbde9420718b58712779ad98fff1ef50349ca0fa7cc0858ae0f826015068654", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:cowboy, "~> 2.10", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowlib, "~> 2.12", [hex: :cowlib, repo: "hexpm", optional: false]}, {:flow, "~> 1.2", [hex: :flow, repo: "hexpm", optional: false]}, {:googleapis, "~> 0.1.0", [hex: :googleapis, repo: "hexpm", optional: false]}, {:gun, "~> 2.0", [hex: :gun, repo: "hexpm", optional: false]}, {:jason, ">= 0.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.5", [hex: :mint, repo: "hexpm", optional: false]}, {:protobuf, "~> 0.14", [hex: :protobuf, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0a5d8673ef16649bef0903bca01c161acfc148e4d269133b6834b2af1f07f45e"}, "gun": {:hex, :gun, "2.2.0", "b8f6b7d417e277d4c2b0dc3c07dfdf892447b087f1cc1caff9c0f556b884e33d", [:make, :rebar3], [{:cowlib, ">= 2.15.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "76022700c64287feb4df93a1795cff6741b83fb37415c40c34c38d2a4645261a"}, "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, - "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, + "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.3", "4252d5d4098da7415c390e847c814bad3764c94a814a0b4245176215615e1035", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "953297c02582a33411ac6208f2c6e55f0e870df7f80da724ed613f10e6706afd"},