github.com/badrootd/nibiru-cometbft@v0.37.5-0.20240307173500-2a75559eee9b/docs/architecture/adr-081-protobuf-mgmt.md (about)

     1  # ADR 081: Protocol Buffers Management
     2  
     3  ## Changelog
     4  
     5  - 2022-02-28: First draft
     6  
     7  ## Status
     8  
     9  Accepted
    10  
    11  [Tracking issue](https://github.com/tendermint/tendermint/issues/8121)
    12  
    13  ## Context
    14  
    15  At present, we manage the [Protocol Buffers] schema files ("protos") that define
    16  our wire-level data formats within the Tendermint repository itself (see the
    17  [`proto`](../../proto/) directory). Recently, we have been making use of [Buf],
    18  both locally and in CI, in order to generate Go stubs, and lint and check
    19  `.proto` files for breaking changes.
    20  
    21  The version of Buf used at the time of this decision was `v1beta1`, and it was
    22  discussed in [\#7975] and in weekly calls as to whether we should upgrade to
    23  `v1` and harmonize our approach with that used by the Cosmos SDK. The team
    24  managing the Cosmos SDK was primarily interested in having our protos versioned
    25  and easily accessible from the [Buf] registry.
    26  
    27  The three main sets of stakeholders for the `.proto` files and their needs, as
    28  currently understood, are as follows.
    29  
    30  1. Tendermint needs Go code generated from `.proto` files.
    31  2. Consumers of Tendermint's `.proto` files, specifically projects that want to
    32     interoperate with Tendermint and need to generate code for their own
    33     programming language, want to be able to access these files in a reliable and
    34     efficient way.
    35  3. The Tendermint Core team wants to provide stable interfaces that are as easy
    36     as possible to maintain, on which consumers can depend, and to be able to
    37     notify those consumers promptly when those interfaces change. To this end, we
    38     want to:
    39     1. Prevent any breaking changes from being introduced in minor/patch releases
    40        of Tendermint. Only major version updates should be able to contain
    41        breaking interface changes.
    42     2. Prevent generated code from diverging from the Protobuf schema files.
    43  
    44  There was also discussion surrounding the notion of automated documentation
    45  generation and hosting, but it is not clear at this time whether this would be
    46  that valuable to any of our stakeholders. What will, of course, be valuable at
    47  minimum would be better documentation (in comments) of the `.proto` files
    48  themselves.
    49  
    50  ## Alternative Approaches
    51  
    52  ### Meeting stakeholders' needs
    53  
    54  1. Go stub generation from protos. We could use:
    55     1. [Buf]. This approach has been rather cumbersome up to this point, and it
    56        is not clear what Buf really provides beyond that which `protoc` provides
    57        to justify the additional complexity in configuring Buf for stub
    58        generation.
    59     2. [protoc] - the Protocol Buffers compiler.
    60  2. Notification of breaking changes:
    61     1. Buf in CI for all pull requests to *release* branches only (and not on
    62        `master`).
    63     2. Buf in CI on every pull request to every branch (this was the case at the
    64        time of this decision, and the team decided that the signal-to-noise ratio
    65        for this approach was too low to be of value).
    66  3. `.proto` linting:
    67     1. Buf in CI on every pull request
    68  4. `.proto` formatting:
    69     1. [clang-format] locally and a [clang-format GitHub Action] in CI to check
    70        that files are formatted properly on every pull request.
    71  5. Sharing of `.proto` files in a versioned, reliable manner:
    72     1. Consumers could simply clone the Tendermint repository, check out a
    73        specific commit, tag or branch and manually copy out all of the `.proto`
    74        files they need. This requires no effort from the Tendermint Core team and
    75        will continue to be an option for consumers. The drawback of this approach
    76        is that it requires manual coding/scripting to implement and is brittle in
    77        the face of bigger changes.
    78     2. Uploading our `.proto` files to Buf's registry on every release. This is
    79        by far the most seamless for consumers of our `.proto` files, but requires
    80        the dependency on Buf. This has the additional benefit that the Buf
    81        registry will automatically [generate and host
    82        documentation][buf-docs-gen] for these protos.
    83     3. We could create a process that, upon release, creates a `.zip` file
    84        containing our `.proto` files.
    85  
    86  ### Popular alternatives to Buf
    87  
    88  [Prototool] was not considered as it appears deprecated, and the ecosystem seems
    89  to be converging on Buf at this time.
    90  
    91  ### Tooling complexity
    92  
    93  The more tools we have in our build/CI processes, the more complex and fragile
    94  repository/CI management becomes, and the longer it takes to onboard new team
    95  members. Maintainability is a core concern here.
    96  
    97  ### Buf sustainability and costs
    98  
    99  One of the primary considerations regarding the usage of Buf is whether, for
   100  example, access to its registry will eventually become a
   101  paid-for/subscription-based service and whether this is valuable enough for us
   102  and the ecosystem to pay for such a service. At this time, it appears as though
   103  Buf will never charge for hosting open source projects' protos.
   104  
   105  Another consideration was Buf's sustainability as a project - what happens when
   106  their resources run out? Will there be a strong and broad enough open source
   107  community to continue maintaining it?
   108  
   109  ### Local Buf usage options
   110  
   111  Local usage of Buf (i.e. not in CI) can be accomplished in two ways:
   112  
   113  1. Installing the relevant tools individually.
   114  2. By way of its [Docker image][buf-docker].
   115  
   116  Local installation of Buf requires developers to manually keep their toolchains
   117  up-to-date. The Docker option comes with a number of complexities, including
   118  how the file system permissions of code generated by a Docker container differ
   119  between platforms (e.g. on Linux, Buf-generated code ends up being owned by
   120  `root`).
   121  
   122  The trouble with the Docker-based approach is that we make use of the
   123  [gogoprotobuf] plugin for `protoc`. Continuing to use the Docker-based approach
   124  to using Buf will mean that we will have to continue building our own custom
   125  Docker image with embedded gogoprotobuf.
   126  
   127  Along these lines, we could eventually consider coming up with a [Nix]- or
   128  [redo]-based approach to developer tooling to ensure tooling consistency across
   129  the team and for anyone who wants to be able to contribute to Tendermint.
   130  
   131  ## Decision
   132  
   133  1. We will adopt Buf for now for proto generation, linting, breakage checking
   134     and its registry (mainly in CI, with optional usage locally).
   135  2. Failing CI when checking for breaking changes in `.proto` files will only
   136     happen when performing minor/patch releases.
   137  3. Local tooling will be favored over Docker-based tooling.
   138  
   139  ## Detailed Design
   140  
   141  We currently aim to:
   142  
   143  1. Update to Buf `v1` to facilitate linting, breakage checking and uploading to
   144     the Buf registry.
   145  2. Configure CI appropriately for proto management:
   146     1. Uploading protos to the Buf registry on every release (e.g. the
   147        [approach][cosmos-sdk-buf-registry-ci] used by the Cosmos SDK).
   148     2. Linting on every pull request (e.g. the
   149        [approach][cosmos-sdk-buf-linting-ci] used by the Cosmos SDK). The linter
   150        passing should be considered a requirement for accepting PRs.
   151     3. Checking for breaking changes in minor/patch version releases and failing
   152        CI accordingly - see [\#8003].
   153     4. Add [clang-format GitHub Action] to check `.proto` file formatting. Format
   154        checking should be considered a requirement for accepting PRs.
   155  3. Update the Tendermint [`Makefile`](../../Makefile) to primarily facilitate
   156     local Protobuf stub generation, linting, formatting and breaking change
   157     checking. More specifically:
   158     1. This includes removing the dependency on Docker and introducing the
   159        dependency on local toolchain installation. CI-based equivalents, where
   160        relevant, will rely on specific GitHub Actions instead of the Makefile.
   161     2. Go code generation will rely on `protoc` directly.
   162  
   163  ## Consequences
   164  
   165  ### Positive
   166  
   167  - We will still offer Go stub generation, proto linting and breakage checking.
   168  - Breakage checking will only happen on minor/patch releases to increase the
   169    signal-to-noise ratio in CI.
   170  - Versioned protos will be made available via Buf's registry upon every release.
   171  
   172  ### Negative
   173  
   174  - Developers/contributors will need to install the relevant Protocol
   175    Buffers-related tooling (Buf, gogoprotobuf, clang-format) locally in order to
   176    build, lint, format and check `.proto` files for breaking changes.
   177  
   178  ### Neutral
   179  
   180  ## References
   181  
   182  - [Protocol Buffers]
   183  - [Buf]
   184  - [\#7975]
   185  - [protoc] - The Protocol Buffers compiler
   186  
   187  [Protocol Buffers]: https://developers.google.com/protocol-buffers
   188  [Buf]: https://buf.build/
   189  [\#7975]: https://github.com/tendermint/tendermint/pull/7975
   190  [protoc]: https://github.com/protocolbuffers/protobuf
   191  [clang-format]: https://clang.llvm.org/docs/ClangFormat.html
   192  [clang-format GitHub Action]: https://github.com/marketplace/actions/clang-format-github-action
   193  [buf-docker]: https://hub.docker.com/r/bufbuild/buf
   194  [cosmos-sdk-buf-registry-ci]: https://github.com/cosmos/cosmos-sdk/blob/e6571906043b6751951a42b6546431b1c38b05bd/.github/workflows/proto-registry.yml
   195  [cosmos-sdk-buf-linting-ci]: https://github.com/cosmos/cosmos-sdk/blob/e6571906043b6751951a42b6546431b1c38b05bd/.github/workflows/proto.yml#L15
   196  [\#8003]: https://github.com/tendermint/tendermint/issues/8003
   197  [Nix]: https://nixos.org/
   198  [gogoprotobuf]: https://github.com/cosmos/gogoproto
   199  [Prototool]: https://github.com/uber/prototool
   200  [buf-docs-gen]: https://docs.buf.build/bsr/documentation
   201  [redo]: https://redo.readthedocs.io/en/latest/