envoyproxy / envoyproxy/examples

Add a tested, docs-first native filter build example (`filter-cc`) using bzlmod

Aberta
#1,389 1 comentário 1 reação 2 responsáveis Reivindicada por @phlax Ver no GitHub
enhancement
Linguagem predominante
Shell
Estrelas
74
Forks
38
Merge médio
2d 17h
PRs com merge (30d)
16

Descrição

## Context

envoyproxy/envoy#47155 (docs/bazel: Switch to bzlmod) moves the Envoy docs build to bzlmod. Once it lands, the final phase of the bzlmod migration is unblocked.

It has been agreed that a **hard blocker** for completing the migration is that we provide an example, somewhere, showing how a downstream developer builds an Envoy extension using bzlmod.

- Historically this was covered by `envoy-filter-example`, which has long since stopped being maintained.
- This repo already has one build example — `wasm-cc` — which was recently brought back to working order and is the natural model for a new example.

Whichever path is taken, the end state is the same: a **full, tested example in this repo**. Examples are docs-first, so a working example here covers the documentation requirement as well.

A **dynamic modules (`dynmod`) example** will also be added at some point; the structure/testing approach chosen here should be reusable for that.

## Principles

- **Docs-first.** The example *is* the documentation. `example.rst` + `README.md` + the config/`MODULE.bazel` are what people read and copy.
- **Must be tested.** Every example has a `verify.sh` and is exercised in CI.
- **Tests test the docs — not the other way round.** The tested artefacts must be exactly what is documented (the `MODULE.bazel`, `BUILD`, `envoy.yaml`, etc. that users see). We should not maintain a separate "real" build that the docs merely describe.

## Proposal: `filter-cc`

A native HTTP filter built and statically linked into Envoy with bzlmod, modelled on `wasm-cc`.

```
filter-cc/
├── .bazelrc
├── .bazelversion
├── MODULE.bazel # the thing people actually copy
├── BUILD
├── http_filter.proto # filter config proto
├── http_filter.h / .cc # StreamDecoderFilter that adds a header
├── http_filter_config.cc # NamedHttpFilterConfigFactory + REGISTER_FACTORY
├── http_filter_integration_test.cc
├── envoy.yaml # uses the filter
├── docker-compose.yaml # proxy (from built binary) + echo backend
├── docker-compose-build.yaml # builds the binary via shared/build, as wasm-cc does
├── Dockerfile-proxy
├── verify.sh
├── example.rst
└── README.md
```

Plus `.bcr/filter-cc/{presubmit.yml,source.template.json}` so it is published to the registry alongside `wasm-cc`.

### `MODULE.bazel` (sketch)

```starlark
module(
name = "envoy-example-filter-cc",
version = "0.2.5.envoy",
)

bazel_dep(name = "envoy", version = "1.40.0-dev")
bazel_dep(name = "envoy_api", version = "1.40.0-dev")

bazel_dep(name = "rules_cc", version = "0.2.22")
bazel_dep(name = "protobuf", version = "35.1.bcr.envoy")
bazel_dep(name = "protoc-gen-validate", version = "1.3.0.envoy")
bazel_dep(name = "rules_pkg", version = "1.1.0")

envoy_toolchains_ext = use_extension("@envoy//bazel:extensions.bzl", "envoy_toolchains_extension")
use_repo(envoy_toolchains_ext, "clang_platform")

# Compiler toolchain as dev_dependency — identical setup to wasm-cc/MODULE.bazel
bazel_dep(name = "toolchains_llvm", version = "1.8.0.envoy", dev_dependency = True)
bazel_dep(name = "envoy_toolshed", version = "0.4.10.envoy", dev_dependency = True)
```

The exact `use_extension` wiring (e.g. extension registry / `envoy_build_config`) needs validating against `@envoy//bazel:extensions.bzl` on head once #47155 is merged.

### `BUILD` (sketch)

```starlark
load("@envoy//bazel:envoy_build_system.bzl", "envoy_cc_binary", "envoy_cc_extension", "envoy_cc_test")
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

api_proto_package()

envoy_cc_extension(
name = "http_filter_lib",
srcs = ["http_filter.cc"],
hdrs = ["http_filter.h"],
deps = [
":pkg_cc_proto",
"@envoy//envoy/http:filter_interface",
"@envoy//source/common/http:header_map_lib",
],
)

envoy_cc_extension(
name = "http_filter_config",
srcs = ["http_filter_config.cc"],
deps = [
":http_filter_lib",
"@envoy//envoy/registry",
"@envoy//envoy/server:filter_config_interface",
],
)

envoy_cc_binary(
name = "envoy",
repository = "@envoy",
deps = [
":http_filter_config",
"@envoy//source/exe:envoy_main_entry_lib",
],
)

envoy_cc_test(
name = "http_filter_integration_test",
srcs = ["http_filter_integration_test.cc"],
repository = "@envoy",
deps = [
":http_filter_config",
"@envoy//test/integration:http_integration_lib",
],
)
```

### Filter content

Simplest credible thing: a decoder filter that reads `key`/`val` from its proto config and adds it as a response header — the same as the old `http-filter-example`, which readers may recognise.

## Testing

- **Standalone (`verify.sh`)**: `docker compose -f docker-compose-build.yaml run build` builds `//:envoy` via `shared/build` (same pattern as `wasm_compile_update`), the binary is copied into `Dockerfile-proxy`, `docker compose up`, and the test asserts the filter's header appears on responses. `envoy_cc_test` provides a real integration test for `bazel test //...` and BCR presubmit.
- **Against envoy dev head**: add `bazel_dep(name = "envoy-example-filter-cc", ...)` to `envoy-examples` and to envoy's `docs/MODULE.bazel`, so the `local_path_override` on `envoy` builds/tests it against the current checkout — the same mechanism as `wasm-cc`.
- **Docs**: `example.rst` goes into the sandboxes toctree via the existing `docs_rst` / `examples_docs` genrule; `envoy.yaml` into `:configs` for the config test.

## Related: test the build examples against envoy dev head

The `wasm-cc` example is currently **not** tested in the envoy repo. This is probably bzlmod+ work, but the build examples (`wasm-cc`, `filter-cc`, and later `dynmod`) should be tested against dev head in envoy, as is already done for the rest of the examples. The head-testing mechanism above should be set up so it covers all build examples, not just the new one.

## Open decisions

1. **Full binary vs. library-only in envoy CI.** Building `//:envoy` (a full static link) in `verify_examples` is heavy. Suggested split: BCR presubmit + `verify.sh` build the full binary (that *is* what is being demonstrated); the envoy-side head test only runs `http_filter_integration_test`, which proves the wiring at a fraction of the cost.
2. **Filter content.** Port the old `http-filter-example` header filter vs. inventing something new (suggest porting).

## Blocked by

- envoyproxy/envoy#47155 — the `MODULE.bazel` extension wiring can only be finalised once this is merged.

## Follow-ups

- `dynmod` example (dynamic modules) using the same docs-first/tested structure.
- Test all build examples (`wasm-cc`, `filter-cc`, `dynmod`) against envoy dev head.

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.