Skip to content

Commit 8a5aaae

Browse files
authored
Merge branch 'master' into cmanallen/scm-wrap-raw-response
2 parents 2fb8dba + 93dc014 commit 8a5aaae

File tree

30 files changed

+265
-138
lines changed

30 files changed

+265
-138
lines changed

.agents/skills/hybrid-cloud-rpc/SKILL.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The service's `local_mode` determines where the database-backed implementation r
4141

4242
| Data lives in... | `local_mode` | Decorator on methods | Example |
4343
| ------------------------------------------------- | ------------------ | ------------------------------- | ---------------------------------- |
44-
| Region silo (projects, events, issues, org data) | `SiloMode.CELL` | `@cell_rpc_method(resolve=...)` | `OrganizationService` |
44+
| Cell silo (projects, events, issues, org data) | `SiloMode.CELL` | `@cell_rpc_method(resolve=...)` | `OrganizationService` |
4545
| Control silo (users, auth, billing, org mappings) | `SiloMode.CONTROL` | `@rpc_method` | `OrganizationMemberMappingService` |
4646

4747
**Decision rule**: If the Django models you need to query live in the cell database, use `SiloMode.CELL`. If they live in the control database, use `SiloMode.CONTROL`.
@@ -95,7 +95,7 @@ If your service doesn't fit any of these, add a new entry to the `service_packag
9595

9696
## Step 4: Add or Update Methods
9797

98-
### For REGION silo services
98+
### For CELL silo services
9999

100100
Load `references/resolvers.md` for resolver details.
101101

@@ -217,11 +217,11 @@ Every RPC service needs three categories of tests: **silo mode compatibility**,
217217

218218
### 7.1 Silo mode compatibility with `@all_silo_test`
219219

220-
Every service test class MUST use `@all_silo_test` so tests run in all three modes (MONOLITH, REGION, CONTROL). This ensures the delegation layer works for both local and remote dispatch paths.
220+
Every service test class MUST use `@all_silo_test` so tests run in all three modes (MONOLITH, CELL, CONTROL). This ensures the delegation layer works for both local and remote dispatch paths.
221221

222222
```python
223223
from sentry.testutils.cases import TestCase, TransactionTestCase
224-
from sentry.testutils.silo import all_silo_test, assume_test_silo_mode, create_test_regions
224+
from sentry.testutils.silo import all_silo_test, assume_test_silo_mode, create_test_cells
225225

226226
@all_silo_test
227227
class MyServiceTest(TestCase):
@@ -234,8 +234,8 @@ class MyServiceTest(TestCase):
234234
For tests that need named cells (e.g., testing cell resolution):
235235

236236
```python
237-
@all_silo_test(regions=create_test_regions("us", "eu"))
238-
class MyServiceRegionTest(TransactionTestCase):
237+
@all_silo_test(cells=create_test_cells("us", "eu"))
238+
class MyServiceCellTest(TransactionTestCase):
239239
...
240240
```
241241

@@ -403,7 +403,7 @@ from sentry.testutils.silo import (
403403
cell_silo_test,
404404
assume_test_silo_mode,
405405
assume_test_silo_mode_of,
406-
create_test_regions,
406+
create_test_cells,
407407
)
408408
from sentry.testutils.outbox import outbox_runner
409409
from sentry.testutils.hybrid_cloud import HybridCloudTestMixin
@@ -423,7 +423,7 @@ Before submitting your PR, verify:
423423
- [ ] All RPC method parameters are keyword-only (`*` separator)
424424
- [ ] All parameters have explicit type annotations
425425
- [ ] All types are serializable (primitives, RpcModel, list, Optional, dict, Enum, datetime)
426-
- [ ] Region service methods have `@cell_rpc_method` with appropriate resolver
426+
- [ ] Cell service methods have `@cell_rpc_method` with appropriate resolver
427427
- [ ] Control service methods have `@rpc_method`
428428
- [ ] `@cell_rpc_method` / `@rpc_method` comes BEFORE `@abstractmethod`
429429
- [ ] `create_delegation()` is called at module level at the bottom of service.py

.agents/skills/hybrid-cloud-test-gen/SKILL.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,17 @@ RPC service tests must cover:
6565

6666
### Quick Reference — Decorator & Base Class
6767

68-
| Scenario | Decorator | Base Class |
69-
| ---------------------------------- | --------------------------------------------------- | -------------------------------- |
70-
| Standard RPC service | `@all_silo_test` | `TestCase` |
71-
| RPC with named regions | `@all_silo_test(regions=create_test_regions("us"))` | `TestCase` |
72-
| RPC with member mapping assertions | `@all_silo_test` | `TestCase, HybridCloudTestMixin` |
68+
| Scenario | Decorator | Base Class |
69+
| ---------------------------------- | ----------------------------------------------- | -------------------------------- |
70+
| Standard RPC service | `@all_silo_test` | `TestCase` |
71+
| RPC with named cells | `@all_silo_test(cells=create_test_cells("us"))` | `TestCase` |
72+
| RPC with member mapping assertions | `@all_silo_test` | `TestCase, HybridCloudTestMixin` |
7373

7474
## Step 4: Generate API Gateway Tests
7575

7676
Load `references/api-gateway-tests.md` for complete templates and patterns.
7777

78-
API gateway tests verify that requests to control-silo endpoints are correctly proxied to the appropriate region. They must cover:
78+
API gateway tests verify that requests to control-silo endpoints are correctly proxied to the appropriate cell. They must cover:
7979

8080
- **Proxy pass-through**: Requests forwarded with correct params, headers, body
8181
- **Query parameter forwarding**: Multi-value params preserved
@@ -84,9 +84,9 @@ API gateway tests verify that requests to control-silo endpoints are correctly p
8484

8585
### Quick Reference — Decorator & Base Class
8686

87-
| Scenario | Decorator | Base Class |
88-
| --------------------- | ------------------------------------------------------------------------------------ | -------------------- |
89-
| Standard gateway test | `@control_silo_test(regions=[ApiGatewayTestCase.REGION], include_monolith_run=True)` | `ApiGatewayTestCase` |
87+
| Scenario | Decorator | Base Class |
88+
| --------------------- | -------------------------------------------------------------------------------- | -------------------- |
89+
| Standard gateway test | `@control_silo_test(cells=[ApiGatewayTestCase.CELL], include_monolith_run=True)` | `ApiGatewayTestCase` |
9090

9191
## Step 5: Generate Outbox Pattern Tests
9292

@@ -120,12 +120,12 @@ Endpoint silo tests verify that API endpoints work correctly under their declare
120120

121121
### Quick Reference — Decorator Mapping
122122

123-
| Endpoint Decorator | Test Decorator |
124-
| ------------------------------------- | ------------------------------------------------------- |
125-
| `@cell_silo_endpoint ` | `@cell_silo_test` |
126-
| `@control_silo_endpoint` | `@control_silo_test` |
127-
| `@control_silo_endpoint` (with proxy) | `@control_silo_test(regions=create_test_regions("us"))` |
128-
| No decorator (monolith-only) | `@no_silo_test` |
123+
| Endpoint Decorator | Test Decorator |
124+
| ------------------------------------- | --------------------------------------------------- |
125+
| `@cell_silo_endpoint ` | `@cell_silo_test` |
126+
| `@control_silo_endpoint` | `@control_silo_test` |
127+
| `@control_silo_endpoint` (with proxy) | `@control_silo_test(cells=create_test_cells("us"))` |
128+
| No decorator (monolith-only) | `@no_silo_test` |
129129

130130
## Step 7: Validate
131131

@@ -153,7 +153,7 @@ from sentry.testutils.silo import (
153153
no_silo_test,
154154
assume_test_silo_mode,
155155
assume_test_silo_mode_of,
156-
create_test_regions,
156+
create_test_cells,
157157
)
158158

159159
# Base classes

.agents/skills/hybrid-cloud-test-gen/references/api-gateway-tests.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ from sentry.utils import json
2626
## Template: Standard API Gateway Test
2727

2828
```python
29-
@control_silo_test(regions=[ApiGatewayTestCase.REGION], include_monolith_run=True)
29+
@control_silo_test(cells=[ApiGatewayTestCase.CELL], include_monolith_run=True)
3030
class Test{Feature}ApiGateway(ApiGatewayTestCase):
3131

3232
@responses.activate
@@ -36,7 +36,7 @@ class Test{Feature}ApiGateway(ApiGatewayTestCase):
3636
headers = dict(example="this")
3737
responses.add_callback(
3838
responses.GET,
39-
f"{self.REGION.address}/organizations/{self.organization.slug}/{endpoint_path}/",
39+
f"{self.CELL.address}/organizations/{self.organization.slug}/{endpoint_path}/",
4040
verify_request_params(query_params, headers),
4141
)
4242

@@ -58,7 +58,7 @@ class Test{Feature}ApiGateway(ApiGatewayTestCase):
5858
headers = {"content-type": "application/json"}
5959
responses.add_callback(
6060
responses.POST,
61-
f"{self.REGION.address}/organizations/{self.organization.slug}/{endpoint_path}/",
61+
f"{self.CELL.address}/organizations/{self.organization.slug}/{endpoint_path}/",
6262
verify_request_body(request_body, headers),
6363
)
6464

@@ -80,7 +80,7 @@ class Test{Feature}ApiGateway(ApiGatewayTestCase):
8080
"""Verify upstream errors are forwarded to the client."""
8181
responses.add(
8282
responses.GET,
83-
f"{self.REGION.address}/organizations/{self.organization.slug}/{endpoint_path}/",
83+
f"{self.CELL.address}/organizations/{self.organization.slug}/{endpoint_path}/",
8484
status=400,
8585
json={"detail": "Bad request"},
8686
)
@@ -104,7 +104,7 @@ In CONTROL mode, proxied responses are streamed. Use `close_streaming_response()
104104
"""Verify proxied response content is correct."""
105105
responses.add_callback(
106106
responses.GET,
107-
f"{self.REGION.address}/organizations/{self.organization.slug}/{endpoint_path}/",
107+
f"{self.CELL.address}/organizations/{self.organization.slug}/{endpoint_path}/",
108108
verify_request_params({}, {}),
109109
)
110110

@@ -128,20 +128,20 @@ In CONTROL mode, proxied responses are streamed. Use `close_streaming_response()
128128
## Template: SiloLimit Availability Check
129129

130130
```python
131-
def test_control_only_endpoint_unavailable_in_region(self):
131+
def test_control_only_endpoint_unavailable_in_cell(self):
132132
"""Verify control-only endpoints raise AvailabilityError outside their silo."""
133133
with pytest.raises(SiloLimit.AvailabilityError):
134134
self.client.get("/api/0/{control-only-path}/")
135135
```
136136

137137
## Key Patterns
138138

139-
- **`ApiGatewayTestCase`** sets up a test region, mock HTTP callbacks, and the API gateway middleware. It extends `APITestCase`.
140-
- **`@control_silo_test(regions=[...], include_monolith_run=True)`** runs the test in both CONTROL and MONOLITH modes.
141-
- **Every test method MUST use `@responses.activate`** because gateway tests mock HTTP calls to the region address.
139+
- **`ApiGatewayTestCase`** sets up a test cell, mock HTTP callbacks, and the API gateway middleware. It extends `APITestCase`.
140+
- **`@control_silo_test(cells=[...], include_monolith_run=True)`** runs the test in both CONTROL and MONOLITH modes.
141+
- **Every test method MUST use `@responses.activate`** because gateway tests mock HTTP calls to the cell address.
142142
- **`verify_request_params(params, headers)`** is a callback that asserts query params and headers match.
143143
- **`verify_request_body(body, headers)`** asserts POST body matches.
144144
- **`close_streaming_response(resp)`** reads a streaming response to bytes — required for proxied responses in CONTROL mode.
145145
- **`override_settings(MIDDLEWARE=tuple(self.middleware))`** ensures the API gateway middleware is active.
146-
- **`self.REGION`** is a pre-configured `Region` object with address `http://us.internal.sentry.io`.
147-
- **`self.organization`** is pre-created in `setUp` and bound to `self.REGION`.
146+
- **`self.CELL`** is a pre-configured `Cell` object with address `http://us.internal.sentry.io`.
147+
- **`self.organization`** is pre-created in `setUp` and bound to `self.CELL`.

.agents/skills/hybrid-cloud-test-gen/references/endpoint-silo-tests.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ from sentry.testutils.silo import (
1010
no_silo_test,
1111
assume_test_silo_mode,
1212
assume_test_silo_mode_of,
13-
create_test_regions,
13+
create_test_cells,
1414
)
1515
from sentry.silo.base import SiloMode
1616
```
@@ -19,14 +19,14 @@ from sentry.silo.base import SiloMode
1919

2020
Match the endpoint's silo decorator to the test's silo decorator:
2121

22-
| Endpoint Decorator | Test Decorator |
23-
| -------------------------------------------- | ------------------------------------------------------- |
24-
| `@cell_silo_endpoint` | `@cell_silo_test` |
25-
| `@control_silo_endpoint` | `@control_silo_test` |
26-
| `@control_silo_endpoint` (proxies to region) | `@control_silo_test(regions=create_test_regions("us"))` |
27-
| No silo decorator | `@no_silo_test` |
22+
| Endpoint Decorator | Test Decorator |
23+
| ------------------------------------------ | --------------------------------------------------- |
24+
| `@cell_silo_endpoint` | `@cell_silo_test` |
25+
| `@control_silo_endpoint` | `@control_silo_test` |
26+
| `@control_silo_endpoint` (proxies to cell) | `@control_silo_test(cells=create_test_cells("us"))` |
27+
| No silo decorator | `@no_silo_test` |
2828

29-
## Template: Region Silo Endpoint Test
29+
## Template: Cell Silo Endpoint Test
3030

3131
```python
3232
@cell_silo_test

.agents/skills/hybrid-cloud-test-gen/references/rpc-service-tests.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ from sentry.testutils.silo import (
2727
all_silo_test,
2828
assume_test_silo_mode,
2929
assume_test_silo_mode_of,
30-
create_test_regions,
30+
create_test_cells,
3131
)
3232
```
3333

@@ -92,7 +92,7 @@ class Test{ServiceName}Service(TestCase):
9292
Prefer `assume_test_silo_mode_of(Model)` over `assume_test_silo_mode(SiloMode.X)` when checking a single model:
9393

9494
```python
95-
@all_silo_test(regions=create_test_regions("us"))
95+
@all_silo_test(cells=create_test_cells("us"))
9696
class Test{ServiceName}CrossSilo(TestCase, HybridCloudTestMixin):
9797
def test_{method_name}_creates_mapping(self):
9898
with outbox_runner():

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ tests/sentry/api/endpoints/test_organization_attribute_mappings.py @get
294294

295295
/src/sentry/search/events/ @getsentry/data-browsing
296296
/src/sentry/search/eap/ @getsentry/data-browsing
297+
/src/sentry/search/exceptions.py @getsentry/data-browsing
297298

298299
/src/sentry/issue_detection/ @getsentry/issue-detection-backend
299300
/tests/sentry/issue_detection/ @getsentry/issue-detection-backend

src/sentry/features/temporary.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ def register_temporary_features(manager: FeatureManager) -> None:
116116
manager.add("organizations:dynamic-sampling-custom", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
117117
# Enable dynamic sampling minimum sample rate
118118
manager.add("organizations:dynamic-sampling-minimum-sample-rate", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
119+
# Enable explore -> errors ui
120+
manager.add("organizations:explore-errors", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
119121
# Enable returning the migrated discover queries in explore saved queries
120122
manager.add("organizations:expose-migrated-discover-queries", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
121123
# Enable GenAI features such as Autofix and Issue Summary

src/sentry/hybridcloud/services/control_organization_provisioning/model.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ class RpcOrganizationSlugReservation(RpcModel):
1010
organization_id: int
1111
user_id: int | None
1212
slug: str
13-
region_name: str
13+
cell_name: str
1414
reservation_type: int
1515

1616
@root_validator(pre=True)
1717
@classmethod
18-
def _accept_cell_name(cls, values: dict[str, Any]) -> dict[str, Any]:
19-
if "cell_name" in values and "region_name" not in values:
20-
values["region_name"] = values.pop("cell_name")
18+
def _accept_region_name(cls, values: dict[str, Any]) -> dict[str, Any]:
19+
if "region_name" in values and "cell_name" not in values:
20+
values["cell_name"] = values.pop("region_name")
2121
return values
2222

2323
@property
24-
def cell_name(self) -> str:
25-
return self.region_name
24+
def region_name(self) -> str:
25+
return self.cell_name

src/sentry/hybridcloud/services/control_organization_provisioning/serial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def serialize_slug_reservation(
1111
id=slug_reservation.id,
1212
organization_id=slug_reservation.organization_id,
1313
slug=slug_reservation.slug,
14-
region_name=slug_reservation.cell_name,
14+
cell_name=slug_reservation.cell_name,
1515
user_id=slug_reservation.user_id,
1616
reservation_type=slug_reservation.reservation_type,
1717
)

src/sentry/incidents/utils/process_update_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from sentry.incidents.utils.types import QuerySubscriptionUpdate
77
from sentry.search.eap.utils import add_start_end_conditions
8-
from sentry.search.events.datasets.discover import InvalidIssueSearchQuery
8+
from sentry.search.exceptions import InvalidIssueSearchQuery
99
from sentry.snuba.dataset import Dataset
1010
from sentry.snuba.entity_subscription import (
1111
ENTITY_TIME_COLUMNS,

0 commit comments

Comments
 (0)