From c9b94d1ea6109471d1eb8a84c5019cfa3157563a Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Fri, 3 Jul 2026 10:08:19 +0200 Subject: [PATCH 1/2] feat(upload): Remove feature flag --- relay-dynamic-config/src/feature.rs | 3 -- relay-server/src/endpoints/upload.rs | 4 +- tests/integration/test_attachment_ref.py | 10 +---- tests/integration/test_minidump.py | 7 +--- tests/integration/test_playstation.py | 1 - tests/integration/test_upload.py | 48 ++++++------------------ 6 files changed, 16 insertions(+), 57 deletions(-) diff --git a/relay-dynamic-config/src/feature.rs b/relay-dynamic-config/src/feature.rs index 9d654755203..a14dade11fc 100644 --- a/relay-dynamic-config/src/feature.rs +++ b/relay-dynamic-config/src/feature.rs @@ -97,9 +97,6 @@ pub enum Feature { /// Enable the experimental Trace Attachment pipeline in Relay. #[serde(rename = "projects:trace-attachment-processing")] TraceAttachmentProcessing, - /// Enable the upload endpoint for attachments. - #[serde(rename = "projects:relay-upload-endpoint")] - UploadEndpoint, /// Upload non-prosperodmp playstation attachments via the upload endpoint. #[serde(rename = "projects:relay-playstation-uploads")] PlaystationUploads, diff --git a/relay-server/src/endpoints/upload.rs b/relay-server/src/endpoints/upload.rs index 021a7bf51c9..447798af843 100644 --- a/relay-server/src/endpoints/upload.rs +++ b/relay-server/src/endpoints/upload.rs @@ -343,7 +343,6 @@ async fn validate_and_limit( project: Project<'_>, ) -> Result { let mut envelope = Envelope::from_request(None, meta); - envelope.require_feature(Feature::UploadEndpoint); let mut item = Item::new(ItemType::Attachment); item.set_payload(ContentType::AttachmentRef, vec![]); item.set_attachment_length(headers.upload_length.unwrap_or(1)); @@ -386,8 +385,7 @@ async fn validate( meta: RequestMeta, project: Project<'_>, ) -> Result { - let mut envelope = Envelope::from_request(None, meta); - envelope.require_feature(Feature::UploadEndpoint); + let envelope = Envelope::from_request(None, meta); let mut envelope = Managed::from_envelope(envelope, state.outcome_aggregator().clone()); let _ = project diff --git a/tests/integration/test_attachment_ref.py b/tests/integration/test_attachment_ref.py index 73f258a65fb..5c58bcf0a41 100644 --- a/tests/integration/test_attachment_ref.py +++ b/tests/integration/test_attachment_ref.py @@ -6,6 +6,7 @@ from sentry_relay.consts import DataCategory from sentry_sdk.envelope import Envelope, Item, PayloadRef + from .asserts import matches_any from .test_store import make_transaction @@ -112,9 +113,6 @@ def test_attachment_ref_ratelimit( project_id = 42 project_config = mini_sentry.add_full_project_config(project_id) - project_config["config"].setdefault("features", []).append( - "projects:relay-upload-endpoint" - ) project_config["config"]["quotas"] = [ { "id": f"test_rate_limiting_{uuid.uuid4().hex}", @@ -170,10 +168,7 @@ def test_attachment_ref( ): event_id = "515539018c9b4260a6f999572f1661ee" project_id = 42 - project_config = mini_sentry.add_full_project_config(project_id) - project_config["config"].setdefault("features", []).append( - "projects:relay-upload-endpoint" - ) + mini_sentry.add_full_project_config(project_id) mini_sentry.global_config["options"][ "relay.objectstore-attachments.sample-rate" ] = 1.0 @@ -257,7 +252,6 @@ def test_attachment_ref_validation( project_config = mini_sentry.add_full_project_config(project_id) project_config["config"].setdefault("features", []).extend( [ - "projects:relay-upload-endpoint", "organizations:relay-generate-billing-outcome", ] ) diff --git a/tests/integration/test_minidump.py b/tests/integration/test_minidump.py index 9dda28003ea..f61aa3d05f6 100644 --- a/tests/integration/test_minidump.py +++ b/tests/integration/test_minidump.py @@ -929,10 +929,7 @@ def test_minidump_placeholder( """ event_id = "515539018c9b4260a6f999572f1661ee" project_id = 42 - project_config = mini_sentry.add_full_project_config(project_id) - project_config["config"].setdefault("features", []).append( - "projects:relay-upload-endpoint" - ) + mini_sentry.add_full_project_config(project_id) mini_sentry.global_config["options"][ "relay.objectstore-attachments.sample-rate" ] = 1.0 @@ -1184,7 +1181,6 @@ def test_minidump_objectstore_uploads_external_chain( project_config["config"].setdefault("features", []).extend( [ "projects:relay-minidump-attachment-uploads", - "projects:relay-upload-endpoint", ] ) @@ -1224,7 +1220,6 @@ def test_minidump_objectstore_uploads_external_chain_attachment_limited( project_config["config"].setdefault("features", []).extend( [ "projects:relay-minidump-attachment-uploads", - "projects:relay-upload-endpoint", "projects:relay-minidump-uploads", ] ) diff --git a/tests/integration/test_playstation.py b/tests/integration/test_playstation.py index d975bf52754..e68949143c2 100644 --- a/tests/integration/test_playstation.py +++ b/tests/integration/test_playstation.py @@ -30,7 +30,6 @@ def playstation_project_config(): "features": [ "organizations:relay-playstation-ingestion", "organizations:relay-new-error-processing", - "projects:relay-upload-endpoint", "projects:relay-playstation-uploads", ], } diff --git a/tests/integration/test_upload.py b/tests/integration/test_upload.py index 3adc2a53e79..684b2c44423 100644 --- a/tests/integration/test_upload.py +++ b/tests/integration/test_upload.py @@ -7,48 +7,35 @@ from concurrent.futures import ThreadPoolExecutor, as_completed from flask import Response -from enum import Enum import pytest from .consts import DUMMY_UPLOAD_PATH, DUMMY_UPLOAD_LOCATION -class FeatureState(Enum): - ENABLED = "enabled" - DISABLED = "disabled" - KILLSWITCHED = "killswitched" - - @pytest.fixture def project_config(mini_sentry): project_id = 42 config = mini_sentry.add_full_project_config(project_id)["config"] - config.setdefault("features", []).append("projects:relay-upload-endpoint") config.setdefault("features", []).append("projects:relay-minidump-uploads") return config @pytest.mark.parametrize( - "feature_state,expected_status_code", + "killswitched,expected_status_code", [ - pytest.param(FeatureState.ENABLED, 201, id="feature enabled"), - pytest.param(FeatureState.DISABLED, 403, id="feature disabled"), - pytest.param(FeatureState.KILLSWITCHED, 503, id="killswitch active"), + pytest.param(False, 201, id="killswitch off"), + pytest.param(True, 503, id="killswitch on"), ], ) def test_forward_create( - mini_sentry, relay, dummy_upload, feature_state, expected_status_code + mini_sentry, relay, dummy_upload, killswitched, expected_status_code ): project_id = 42 - config = mini_sentry.add_full_project_config(project_id) - if feature_state is FeatureState.KILLSWITCHED: + mini_sentry.add_full_project_config(project_id) + if killswitched: mini_sentry.global_config["options"][ "relay.endpoint-fetch-config.enabled" ] = False - if feature_state is FeatureState.ENABLED: - config["config"].setdefault("features", []).append( - "projects:relay-upload-endpoint" - ) relay = relay(mini_sentry) response = relay.post( @@ -64,26 +51,21 @@ def test_forward_create( @pytest.mark.parametrize( - "feature_state,expected_status_code", + "killswitched,expected_status_code", [ - pytest.param(FeatureState.ENABLED, 204, id="feature enabled"), - pytest.param(FeatureState.DISABLED, 403, id="feature disabled"), - pytest.param(FeatureState.KILLSWITCHED, 503, id="killswitch active"), + pytest.param(False, 204, id="killswitch off"), + pytest.param(True, 503, id="killswitch on"), ], ) def test_forward_patch( - mini_sentry, relay, dummy_upload, feature_state, expected_status_code + mini_sentry, relay, dummy_upload, killswitched, expected_status_code ): project_id = 42 - config = mini_sentry.add_full_project_config(project_id) - if feature_state is FeatureState.KILLSWITCHED: + mini_sentry.add_full_project_config(project_id) + if killswitched: mini_sentry.global_config["options"][ "relay.endpoint-fetch-config.enabled" ] = False - if feature_state is FeatureState.ENABLED: - config["config"].setdefault("features", []).append( - "projects:relay-upload-endpoint" - ) relay = relay(mini_sentry) data = b"hello world" @@ -99,11 +81,6 @@ def test_forward_patch( ) assert response.status_code == expected_status_code, response.text - if feature_state is FeatureState.DISABLED: - assert ( - response.json()["detail"] - == "event submission rejected with_reason: FeatureDisabled(UploadEndpoint)" - ) def test_post_retries(mini_sentry, relay, project_config): @@ -677,7 +654,6 @@ def test_upload_minidump_opt_in( project_id = 42 config = mini_sentry.add_full_project_config(project_id)["config"] features = config.setdefault("features", []) - features.append("projects:relay-upload-endpoint") if opted_in: features.append("projects:relay-minidump-uploads") From 472a524e20f84e5db4bed7497ceab851ab7e0f8b Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Mon, 6 Jul 2026 08:30:16 +0200 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d43a7c460a4..9eccbb9d9a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Raises the size limit for the flags context to 64KiB. ([#6137](https://github.com/getsentry/relay/pull/6137)) - Add segment_names field to Replay events. ([#6134](https://github.com/getsentry/relay/pull/6134)) - Support PEM file format for signing / verification keys. ([#6155](https://github.com/getsentry/relay/pull/6155)) +- GA the `upload-endpoint` feature. ([#6171](https://github.com/getsentry/relay/pull/6171)) **Bug Fixes**: