Skip to content

Commit

Permalink
Merge branch 'master' into jodi/notification_uuid_digests
Browse files Browse the repository at this point in the history
# Conflicts:
#	tests/sentry/notifications/notifications/test_digests.py
  • Loading branch information
scttcper committed Sep 13, 2023
2 parents 18aad3f + cf29f5e commit e9d3156
Show file tree
Hide file tree
Showing 64 changed files with 1,906 additions and 365 deletions.
11 changes: 0 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -427,12 +427,10 @@ module = [
"sentry.integrations.bitbucket.installed",
"sentry.integrations.bitbucket.integration",
"sentry.integrations.bitbucket.issues",
"sentry.integrations.bitbucket.repository",
"sentry.integrations.bitbucket.uninstalled",
"sentry.integrations.bitbucket.webhook",
"sentry.integrations.bitbucket_server.client",
"sentry.integrations.bitbucket_server.integration",
"sentry.integrations.bitbucket_server.repository",
"sentry.integrations.bitbucket_server.webhook",
"sentry.integrations.example.integration",
"sentry.integrations.example.repository",
Expand All @@ -443,12 +441,10 @@ module = [
"sentry.integrations.github.webhook",
"sentry.integrations.github_enterprise.client",
"sentry.integrations.github_enterprise.integration",
"sentry.integrations.github_enterprise.repository",
"sentry.integrations.github_enterprise.webhook",
"sentry.integrations.gitlab.client",
"sentry.integrations.gitlab.integration",
"sentry.integrations.gitlab.issues",
"sentry.integrations.gitlab.repository",
"sentry.integrations.gitlab.webhooks",
"sentry.integrations.jira.actions.create_ticket",
"sentry.integrations.jira.actions.form",
Expand Down Expand Up @@ -520,9 +516,6 @@ module = [
"sentry.issues.search",
"sentry.issues.status_change",
"sentry.mail.adapter",
"sentry.mail.forms.assigned_to",
"sentry.mail.forms.member_team",
"sentry.mail.forms.notify_email",
"sentry.mail.notifications",
"sentry.management.commands.makemigrations",
"sentry.management.commands.send_fake_data",
Expand Down Expand Up @@ -582,12 +575,8 @@ module = [
"sentry.plugins.endpoints",
"sentry.plugins.helpers",
"sentry.plugins.providers.base",
"sentry.plugins.providers.dummy.repository",
"sentry.plugins.providers.integration_repository",
"sentry.plugins.providers.repository",
"sentry.plugins.sentry_interface_types.models",
"sentry.plugins.sentry_urls.models",
"sentry.plugins.sentry_useragents.models",
"sentry.plugins.sentry_webhooks.plugin",
"sentry.plugins.validators.url",
"sentry.profiles.task",
Expand Down
23 changes: 20 additions & 3 deletions src/minimetrics/core.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import threading
import time
import zlib
Expand Down Expand Up @@ -181,10 +182,24 @@ def __init__(self) -> None:
self._flush_event: Event = Event()
# Use to signal whether we want to flush the buckets in the next loop iteration, irrespectively of the cutoff.
self._force_flush: bool = False

# Thread handling the flushing loop.
self._flusher: Optional[Thread] = Thread(target=self._flush_loop)
self._flusher.daemon = True
self._flusher.start()
self._flusher: Optional[Thread] = None
self._flusher_pid: Optional[int] = None
self._ensure_thread()

def _ensure_thread(self):
"""For forking processes we might need to restart this thread.
This ensures that our process actually has that thread running.
"""
pid = os.getpid()
if self._flusher_pid == pid:
return
with self._lock:
self._flusher_pid = pid
self._flusher = Thread(target=self._flush_loop)
self._flusher.daemon = True
self._flusher.start()

def _flush_loop(self) -> None:
while self._running or self._force_flush:
Expand Down Expand Up @@ -231,6 +246,8 @@ def add(
tags: Optional[MetricTagsExternal],
timestamp: Optional[float],
) -> None:
self._ensure_thread()

if self._flusher is None:
return

Expand Down
13 changes: 10 additions & 3 deletions src/sentry/api/endpoints/debug_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from sentry.api.exceptions import ResourceDoesNotExist
from sentry.api.paginator import OffsetPaginator
from sentry.api.serializers import serialize
from sentry.auth.access import Access
from sentry.auth.superuser import is_active_superuser
from sentry.auth.system import is_system_auth
from sentry.constants import DEBUG_FILES_ROLE_DEFAULT, KNOWN_DIF_FORMATS
Expand All @@ -35,6 +36,7 @@
create_files_from_dif_zip,
)
from sentry.models.debugfile import ProguardArtifactRelease
from sentry.models.project import Project
from sentry.models.release import get_artifact_counts
from sentry.tasks.assemble import (
AssembleTask,
Expand Down Expand Up @@ -87,6 +89,12 @@ def has_download_permission(request, project):
return roles.get(current_role).priority >= roles.get(required_role).priority


def _has_delete_permission(access: Access, project: Project) -> bool:
if access.has_scope("project:write"):
return True
return access.has_project_scope(project, "project:write")


@region_silo_endpoint
class ProguardArtifactReleasesEndpoint(ProjectEndpoint):
publish_status = {
Expand Down Expand Up @@ -296,7 +304,7 @@ def on_results(difs: Sequence[ProjectDebugFile]):
on_results=on_results,
)

def delete(self, request: Request, project) -> Response:
def delete(self, request: Request, project: Project) -> Response:
"""
Delete a specific Project's Debug Information File
```````````````````````````````````````````````````
Expand All @@ -310,8 +318,7 @@ def delete(self, request: Request, project) -> Response:
:qparam string id: The id of the DIF to delete.
:auth: required
"""

if request.GET.get("id") and (request.access.has_scope("project:write")):
if request.GET.get("id") and _has_delete_permission(request.access, project):
with atomic_transaction(using=router.db_for_write(File)):
debug_file = (
ProjectDebugFile.objects.filter(id=request.GET.get("id"), project_id=project.id)
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/group_notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def post(self, request: Request, group) -> Response:
)

GroupSubscription.objects.subscribe(
group=group, user=request.user, reason=GroupSubscriptionReason.comment
group=group, subscriber=request.user, reason=GroupSubscriptionReason.comment
)

mentioned_users = extract_user_ids_from_mentions(group.organization.id, mentions)
Expand Down
17 changes: 9 additions & 8 deletions src/sentry/api/endpoints/integrations/doc_integrations/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ def post(self, request: Request):
data = request.json_body
data["is_draft"] = True
data["metadata"] = self.generate_incoming_metadata(request)

serializer = DocIntegrationSerializer(data=data)
if serializer.is_valid():
doc_integration = serializer.save()
return Response(
serialize(doc_integration, request.user),
status=status.HTTP_201_CREATED,
)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

doc_integration = serializer.save()
return Response(
serialize(doc_integration, request.user),
status=status.HTTP_201_CREATED,
)
4 changes: 2 additions & 2 deletions src/sentry/api/helpers/group_index/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def self_subscribe_and_assign_issue(
# representation of current user
if acting_user:
GroupSubscription.objects.subscribe(
user=acting_user, group=group, reason=GroupSubscriptionReason.status_change
subscriber=acting_user, group=group, reason=GroupSubscriptionReason.status_change
)

if self_assign_issue == "1" and not group.assignee_set.exists():
Expand Down Expand Up @@ -736,7 +736,7 @@ def handle_is_bookmarked(
user_id=acting_user.id if acting_user else None,
)
GroupSubscription.objects.subscribe(
user=acting_user, group=group, reason=GroupSubscriptionReason.bookmark
subscriber=acting_user, group=group, reason=GroupSubscriptionReason.bookmark
)
elif is_bookmarked is False:
GroupBookmark.objects.filter(
Expand Down
9 changes: 9 additions & 0 deletions src/sentry/api/serializers/rest_framework/doc_integration.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random
import string
from typing import Any, MutableMapping

from django.db import router, transaction
Expand All @@ -6,6 +8,7 @@
from rest_framework import serializers
from rest_framework.serializers import Serializer, ValidationError

from sentry import options
from sentry.api.fields.avatar import AvatarField
from sentry.api.serializers.rest_framework.sentry_app import URLField
from sentry.api.validators.doc_integration import validate_metadata_schema
Expand Down Expand Up @@ -59,6 +62,12 @@ def validate_name(self, value: str) -> str:

def create(self, validated_data: MutableMapping[str, Any]) -> DocIntegration:
slug = self._generate_slug(validated_data["name"])

# If option is set, add random 3 lowercase letter suffix to prevent numeric slug
# eg: 123 -> 123-abc
if options.get("api.prevent-numeric-slugs") and slug.isdecimal():
slug = f"{slug}-{''.join(random.choice(string.ascii_lowercase) for _ in range(3))}"

features = validated_data.pop("features") if validated_data.get("features") else []
with transaction.atomic(router.db_for_write(DocIntegration)):
doc_integration = DocIntegration.objects.create(slug=slug, **validated_data)
Expand Down
7 changes: 7 additions & 0 deletions src/sentry/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
DiscoverSavedQueryVisitEndpoint,
)
from sentry.feedback.endpoints.feedback_ingest import FeedbackIngestEndpoint
from sentry.feedback.endpoints.organization_feedback_index import OrganizationFeedbackIndexEndpoint
from sentry.incidents.endpoints.organization_alert_rule_available_action_index import (
OrganizationAlertRuleAvailableActionIndexEndpoint,
)
Expand Down Expand Up @@ -1746,6 +1747,12 @@
OrganizationTransactionAnomalyDetectionEndpoint.as_view(),
name="sentry-api-0-organization-transaction-anomaly-detection",
),
# Feedback
re_path(
r"^(?P<organization_slug>[^\/]+)/feedback/$",
OrganizationFeedbackIndexEndpoint.as_view(),
name="sentry-api-0-organization-feedback-index",
),
# relay usage
re_path(
r"^(?P<organization_slug>[^\/]+)/relay_usage/$",
Expand Down
Loading

0 comments on commit e9d3156

Please sign in to comment.