envoyproxy/envoy
Development workflow
The end-to-end lifecycle of a change to Envoy.
1. Communicate (for anything > ~100 LOC)
For anything beyond a small bugfix or doc tweak, open or comment on a GitHub issue first. The contributing guide defines a "major feature" as anything > 100 LOC altered (excluding tests) or anything that changes user-facing behavior, and asks for an issue + design discussion before code is written. New extensions in particular have their own gatekeeping process — see EXTENSION_POLICY.md.
2. Branch and code
Fork the repo and branch from main. Use a descriptive branch name; there is no enforced convention. Sign off every commit (git commit -s) for the DCO.
While editing:
- Match the existing file's style. Read patterns and conventions before writing new code.
- Keep public interfaces in
envoy/abstract (pure virtual). Implementation goes insource/. - If you add a new public interface, add a corresponding mock under
test/mocks/. - If you add a new extension, register it in
source/extensions/extensions_build_config.bzl(orall_extensions.bzlfor non-removable ones), add metadata toextensions_metadata.yaml, and add CODEOWNERS entries.
3. Format and lint
Before pushing:
# Repo-wide format check (read-only)
tools/code_format/check_format.py check
# Apply formatting fixes in place
tools/code_format/check_format.py fix
# Faster: only check files changed against main
./tools/local_fix_format.sh
# clang-tidy is checked in CI, run locally if you've changed C++:
./ci/run_clang_tidy.shThe .clang-format and .clang-tidy files at the repo root encode the canonical rules. The check_format.py checks include the inclusive-language policy, license headers, banned tokens, ordering of #include blocks, namespace usage, smart-pointer aliasing, ordering of BUILD deps, etc. — many things clang-format doesn't see.
4. Build and test
Local iteration loop:
# Compile core
bazel build -c dbg //source/exe:envoy-static
# Run a focused unit test
bazel test //test/common/http:filter_manager_test
# Run an integration test
bazel test //test/integration:integration_test
# Run with a sanitizer
bazel test --config=asan //test/common/http/...The Testing page goes deeper. The CI configuration mirrors what you can run locally; see ci/ for the canonical scripts.
5. Add a release note (if user-visible)
If the change is user-visible or affects extension developers, add a YAML entry to changelogs/current.yaml. The format is enforced by tools/release_notes/check.py. Entries are alphabetised by subsystem.
Categories:
behavior_changes— changes that may break existing usersminor_behavior_changes— minor effects, runtime-guardedbug_fixes— bug fixesremoved_config_or_runtime— removed deprecated confignew_features— new featuresdeprecated— newly deprecated config
6. Add a runtime guard (if behavioural)
Behavioural changes go behind a runtime feature flag so they can be disabled in production by setting the flag in Bootstrap.layered_runtime or via RTDS. Pattern:
constexpr absl::string_view kMyChangeRuntimeFlag =
"envoy.reloadable_features.my_change_name";
if (Runtime::runtimeFeatureEnabled(kMyChangeRuntimeFlag)) {
// new behaviour
} else {
// old behaviour
}The flag must be registered in source/common/runtime/runtime_features.cc with its default. Most new flags default to true (the new behaviour is on) and exist for emergency rollback. Old flags are removed after a release cycle if no one disables them.
7. Open the PR
Use the PULL_REQUEST_TEMPLATE.md. The fields are explained in PULL_REQUESTS.md:
- Title.
subsystem: brief change description— both lower-case, e.g.router: add x-envoy-overloaded header. - Risk level. Low / Medium / High. Bug fixes are usually Low, new filters Medium, flow-control rewrites High.
- Testing. What you tested. Unit, integration, manual.
- Documentation. Note any docs changes, especially Life of a Request for data-plane structural changes.
- Release notes. Reference your
changelogs/current.yamlchange or writeN/A. - Runtime guard. Name the flag.
- API Considerations. If you touched anything under
api/, walk through the API review checklist.
8. CI
Azure Pipelines runs the full matrix on every push to your PR. The pipeline is defined in .azure-pipelines/ and orchestrated by scripts under ci/. Significant jobs include:
format— runstools/code_format/check_format.py checkand a few other lints.compile_time_options— builds with most options flipped (deprecated features off, FIPS, etc.).gcc,clang,clang_libcxx, sanitizer builds (asan/tsan/msan/ubsan), coverage build, fuzz build.release— producesenvoy-staticand the contrib equivalent forlinux/amd64andlinux/arm64.
You may need to push fixes; CI is mostly stable but flaky integration tests do exist (see the copilot/disable-flaky-... branches in the remote for the kinds of issues that come up).
9. Review
The reviewer team is split into:
- CODEOWNERS for the directory you touched (see
CODEOWNERS). At least one CODEOWNER approval is required. - Senior maintainer for security-sensitive or high-risk changes.
- The reviewers.yaml file feeds the repokitteh bot which auto-assigns reviewers based on the changed paths.
Conventions during review:
- Reviewers leave comments inline; you address them with
git commit --amendorgit commit --fixupand force-push, or with new commits that get squashed at merge. - The
kthxbyeslash command (from repokitteh) is used to auto-merge PRs once everything is green and approved. - "Bumps PR" — comments asking for a re-review after addressing feedback — are common and expected.
10. Merge
The final commit message is the PR description (the GitHub "squash and merge" model). Maintainers will edit your description if it doesn't match the canonical commit-message format. Once merged, your change lands on main and is built by CI for the next nightly Docker image.
Backporting
If your fix is needed in an existing release line, follow BACKPORTS.md: cherry-pick onto release/v1.X, open a PR against that branch, and tag it with backport. Security backports follow SECURITY.md.
See also
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.