feat(protos): Add proto override system for in-repo proto definitions#115251
Draft
feat(protos): Add proto override system for in-repo proto definitions#115251
Conversation
Install a custom import hook that compiles .proto files to _pb2.py modules at import time, bypassing the installed sentry-protos pip package. This eliminates the release cycle friction when iterating on proto definitions during local development. Set SENTRY_PROTO_DEV_DIR to a sentry-protos checkout or place .proto files in {repo_root}/proto/ to activate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split the combined proto_dev_loader module into two focused modules: - proto_compiler: build-time tool that compiles .proto files into _pb2.py modules. Supports CLI usage for CI/deploy pre-compilation. - proto_loader: lightweight runtime import hook that serves pre-compiled pb2 overrides with transparent pip fallback. Works in both development (on-demand compilation) and production (pre-compiled only). Fix namespace shadowing bug: the original finder claimed intermediate packages (sentry_protos.billing, etc.) with search paths pointing only to the cache directory, making pip-installed pb2 modules invisible. The new loader only intercepts _pb2 leaf imports and delegates intermediate packages to pip's finder unless they represent new domains not in pip. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add PROTO_OVERRIDE.md with comprehensive guide covering architecture, quick start for dev and prod, import hook internals, the namespace shadowing bug and its fix, directory structure, CLI reference, API reference, supported import patterns, and troubleshooting. Enhance inline comments in proto_compiler.py and proto_loader.py explaining design decisions: why grpcio-tools is lazily imported, why RLock over Lock, why intermediate packages are delegated to pip, and how _pip_package_has avoids recursion in the MetaPathFinder. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add proto/ directory for committing .proto source files directly to the sentry repo. Files here are auto-detected by proto_loader with highest priority, enabling both local dev (auto-compile on import) and prod (pre-compile during build) without a sentry-protos release. Add bin/sync-protos helper script for syncing proto domains from a sentry-protos checkout into proto/. Supports selective domain sync, batch compilation, and status reporting. Defaults to the billing domain and ../sentry-protos. Update PROTO_OVERRIDE.md with in-repo workflow, priority order docs, switching guide, and getsentry integration instructions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Proto sources live in this repo and are edited here directly. The sync script is a one-time migration tool, not an ongoing workflow. Update README and PROTO_OVERRIDE.md to reflect that proto/ is the source of truth, with pip as fallback for non-migrated domains only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the "Namespace Shadowing Bug" section and other internal implementation narratives from PROTO_OVERRIDE.md. Simplify code comments to explain what matters, not how we got here. Trim verbose docstrings throughout both modules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Call install() in two places so proto overrides are active before any sentry_protos imports: - runner/initializer.py: before django.setup(), which triggers model imports that reference sentry_protos at module level. - testutils/pytest/sentry.py: in pytest_configure, before initialize_app() and test collection. Both calls are no-ops when no proto/ directory or cache exists. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both repos share one venv with sentry editable-installed, so proto overrides work automatically in getsentry with no changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The override is transparent — same import paths work regardless of whether the module comes from proto/ or pip. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Required for proto compilation during development (auto-compile on import) and CI build steps. Not needed in production where protos are pre-compiled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
grpcio-tools is not available on pypi.devinfra.sentry.io yet. Need to add it to getsentry/pypi first before it can be declared as a dependency. For now, it's installed manually or via the existing venv (already present from prior installs). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.protofiles directly from the sentry repo, replacing the pip-installedsentry-protospackage for migrated domainsproto/sentry_protos/and are the source of truth for migrated domains (starting with billing). Non-migrated domains (snuba, seer, etc.) fall back to the pip package transparentlyfrom sentry_protos.billing.v1.data_category_pb2 import DataCategoryworks the same whether the module comes fromproto/or pip. No code migration neededArchitecture
Two modules with distinct responsibilities:
proto_compiler.py— build-time tool that compiles.proto→_pb2.py. Has a CLI for CI/deploy:python -m sentry.utils.proto_compiler compile --source proto --output .proto_cacheproto_loader.py— lightweight runtime import hook. Interceptssentry_protos.*_pb2imports, serves compiled overrides from.proto_cache/, falls back to pip. In dev mode, triggers compilation on demand when sources change. Only intercepts leaf_pb2imports — intermediate packages are left to pip so non-overridden siblings remain importableHookup points
runner/initializer.py—install()called beforedjango.setup(), which triggers model imports that referencesentry_protosat module leveltestutils/pytest/sentry.py—install()called inpytest_configurebeforeinitialize_app()and test collectionproto/directory or cache exists — zero impact on developers not using overridesIncluded
src/sentry/utils/proto_compiler.py.proto→_pb2.pycompiler with CLIsrc/sentry/utils/proto_loader.pysrc/sentry/utils/PROTO_OVERRIDE.mdproto/README.mdbin/sync-protossrc/sentry/runner/initializer.pyinstall()call beforedjango.setup()src/sentry/testutils/pytest/sentry.pyinstall()call inpytest_configuretests/sentry/utils/test_proto_compiler.pytests/sentry/utils/test_proto_loader.pyTest plan
bin/sync-protoscopies billing protos correctly from sentry-protosfrom sentry_protos.billing.v1.data_category_pb2 import DataCategoryworks with in-repo protos