security(deps): Bump django version to 2.2.27
diff --git a/requirements-base.txt b/requirements-base.txt
index cc3e97c8aceac..9aa32dd7a1bc8 100644
--- a/requirements-base.txt
+++ b/requirements-base.txt
@@ -12,7 +12,7 @@ datadog==0.29.3
 django-crispy-forms==1.8.1
 django-picklefield==2.1.0
 django-pg-zero-downtime-migrations==0.10
-Django==2.2.24
+Django==2.2.27
 djangorestframework==3.11.2
 drf-spectacular==0.21.0
 email-reply-parser==0.5.12
diff --git a/src/sentry/web/debug_urls.py b/src/sentry/web/debug_urls.py
index 1e252038a2bdd..742c4e3701577 100644
--- a/src/sentry/web/debug_urls.py
+++ b/src/sentry/web/debug_urls.py
@@ -1,4 +1,4 @@
-from django.conf.urls import url
+from django.urls import re_path
 from django.views.generic import TemplateView
 
 import sentry.web.frontend.debug.mail
@@ -65,67 +65,67 @@
 from sentry.web.frontend.debug.debug_unassigned_email import DebugUnassignedEmailView
 
 urlpatterns = [
-    url(r"^debug/mail/alert/$", sentry.web.frontend.debug.mail.alert),
-    url(r"^debug/mail/note/$", DebugNoteEmailView.as_view()),
-    url(r"^debug/mail/new-release/$", DebugNewReleaseEmailView.as_view()),
-    url(r"^debug/mail/new-user-feedback/$", DebugNewUserFeedbackEmailView.as_view()),
-    url(r"^debug/mail/assigned/$", DebugAssignedEmailView.as_view()),
-    url(r"^debug/mail/assigned/self/$", DebugSelfAssignedEmailView.as_view()),
-    url(r"^debug/mail/assigned/team/$", DebugSelfAssignedTeamEmailView.as_view()),
-    url(
-        r"^debug/mail/codeowners_auto_sync_failure/$", DebugCodeOwnersAutoSyncFailureView.as_view()
+    re_path("^debug/mail/alert", sentry.web.frontend.debug.mail.alert),
+    re_path("^debug/mail/note", DebugNoteEmailView.as_view()),
+    re_path("^debug/mail/new-release", DebugNewReleaseEmailView.as_view()),
+    re_path("^debug/mail/new-user-feedback", DebugNewUserFeedbackEmailView.as_view()),
+    re_path("^debug/mail/assigned/self", DebugSelfAssignedEmailView.as_view()),
+    re_path("^debug/mail/assigned/team", DebugSelfAssignedTeamEmailView.as_view()),
+    re_path("^debug/mail/assigned", DebugAssignedEmailView.as_view()),
+    re_path(
+        "^debug/mail/codeowners_auto_sync_failure", DebugCodeOwnersAutoSyncFailureView.as_view()
     ),
-    url(r"^debug/mail/digest/$", sentry.web.frontend.debug.mail.digest),
-    url(r"^debug/mail/report/$", sentry.web.frontend.debug.mail.report),
-    url(r"^debug/mail/regression/$", DebugRegressionEmailView.as_view()),
-    url(r"^debug/mail/regression/release/$", DebugRegressionReleaseEmailView.as_view()),
-    url(r"^debug/mail/resolved/$", DebugResolvedEmailView.as_view()),
-    url(r"^debug/mail/resolved-in-release/$", DebugResolvedInReleaseEmailView.as_view()),
-    url(
-        r"^debug/mail/resolved-in-release/upcoming/$",
+    re_path("^debug/mail/digest", sentry.web.frontend.debug.mail.digest),
+    re_path("^debug/mail/report", sentry.web.frontend.debug.mail.report),
+    re_path("^debug/mail/regression/release", DebugRegressionReleaseEmailView.as_view()),
+    re_path("^debug/mail/regression", DebugRegressionEmailView.as_view()),
+    re_path(
+        "^debug/mail/resolved-in-release/upcoming",
         DebugResolvedInReleaseUpcomingEmailView.as_view(),
     ),
-    url(r"^debug/mail/request-access/$", sentry.web.frontend.debug.mail.request_access),
-    url(
-        r"^debug/mail/request-access-for-another-member/$",
+    re_path("^debug/mail/resolved-in-release", DebugResolvedInReleaseEmailView.as_view()),
+    re_path("^debug/mail/resolved", DebugResolvedEmailView.as_view()),
+    re_path(
+        "^debug/mail/request-access-for-another-member",
         sentry.web.frontend.debug.mail.request_access_for_another_member,
     ),
-    url(r"^debug/mail/join-request/$", DebugOrganizationJoinRequestEmailView.as_view()),
-    url(r"^debug/mail/invite-request/$", DebugOrganizationInviteRequestEmailView.as_view()),
-    url(r"^debug/mail/access-approved/$", sentry.web.frontend.debug.mail.access_approved),
-    url(r"^debug/mail/invitation/$", sentry.web.frontend.debug.mail.invitation),
-    url(r"^debug/mail/invalid-identity/$", DebugInvalidIdentityEmailView.as_view()),
-    url(r"^debug/mail/codeowners-request/$", DebugCodeOwnersRequestView.as_view()),
-    url(r"^debug/mail/confirm-email/$", sentry.web.frontend.debug.mail.confirm_email),
-    url(r"^debug/mail/recover-account/$", sentry.web.frontend.debug.mail.recover_account),
-    url(r"^debug/mail/unable-to-delete-repo/$", DebugUnableToDeleteRepository.as_view()),
-    url(r"^debug/mail/unable-to-fetch-commits/$", DebugUnableToFetchCommitsEmailView.as_view()),
-    url(r"^debug/mail/unassigned/$", DebugUnassignedEmailView.as_view()),
-    url(r"^debug/mail/org-delete-confirm/$", sentry.web.frontend.debug.mail.org_delete_confirm),
-    url(r"^debug/mail/mfa-removed/$", DebugMfaRemovedEmailView.as_view()),
-    url(r"^debug/mail/mfa-added/$", DebugMfaAddedEmailView.as_view()),
-    url(
-        r"^debug/mail/recovery-codes-regenerated/$",
+    re_path("^debug/mail/request-access", sentry.web.frontend.debug.mail.request_access),
+    re_path("^debug/mail/join-request", DebugOrganizationJoinRequestEmailView.as_view()),
+    re_path("^debug/mail/invite-request", DebugOrganizationInviteRequestEmailView.as_view()),
+    re_path("^debug/mail/access-approved", sentry.web.frontend.debug.mail.access_approved),
+    re_path("^debug/mail/invitation", sentry.web.frontend.debug.mail.invitation),
+    re_path("^debug/mail/invalid-identity", DebugInvalidIdentityEmailView.as_view()),
+    re_path("^debug/mail/codeowners-request", DebugCodeOwnersRequestView.as_view()),
+    re_path("^debug/mail/confirm-email", sentry.web.frontend.debug.mail.confirm_email),
+    re_path("^debug/mail/recover-account", sentry.web.frontend.debug.mail.recover_account),
+    re_path("^debug/mail/unable-to-delete-repo", DebugUnableToDeleteRepository.as_view()),
+    re_path("^debug/mail/unable-to-fetch-commits", DebugUnableToFetchCommitsEmailView.as_view()),
+    re_path("^debug/mail/unassigned", DebugUnassignedEmailView.as_view()),
+    re_path("^debug/mail/org-delete-confirm", sentry.web.frontend.debug.mail.org_delete_confirm),
+    re_path("^debug/mail/mfa-removed", DebugMfaRemovedEmailView.as_view()),
+    re_path("^debug/mail/mfa-added", DebugMfaAddedEmailView.as_view()),
+    re_path(
+        "^debug/mail/recovery-codes-regenerated",
         DebugRecoveryCodesRegeneratedEmailView.as_view(),
     ),
-    url(r"^debug/mail/password-changed/$", DebugPasswordChangedEmailView.as_view()),
-    url(r"^debug/mail/new-processing-issues/$", DebugNewProcessingIssuesEmailView.as_view()),
-    url(
-        r"^debug/mail/new-processing-issues-no-reprocessing/$",
+    re_path("^debug/mail/password-changed", DebugPasswordChangedEmailView.as_view()),
+    re_path(
+        "^debug/mail/new-processing-issues-no-reprocessing",
         DebugNewProcessingIssuesNoReprocessingEmailView.as_view(),
     ),
-    url(r"^debug/mail/sso-linked/$", DebugSsoLinkedEmailView.as_view()),
-    url(r"^debug/mail/sso-unlinked/$", DebugSsoUnlinkedEmailView.as_view()),
-    url(r"^debug/mail/sso-unlinked/no-password$", DebugSsoUnlinkedNoPasswordEmailView.as_view()),
-    url(r"^debug/mail/incident-activity$", DebugIncidentActivityEmailView.as_view()),
-    url(r"^debug/mail/incident-trigger$", DebugIncidentTriggerEmailView.as_view()),
-    url(r"^debug/mail/setup-2fa/$", DebugSetup2faEmailView.as_view()),
-    url(r"^debug/embed/error-page/$", DebugErrorPageEmbedView.as_view()),
-    url(r"^debug/trigger-error/$", DebugTriggerErrorView.as_view()),
-    url(r"^debug/auth-confirm-identity/$", debug_auth_views.DebugAuthConfirmIdentity.as_view()),
-    url(r"^debug/auth-confirm-link/$", debug_auth_views.DebugAuthConfirmLink.as_view()),
-    url(r"^debug/sudo/$", TemplateView.as_view(template_name="sentry/account/sudo.html")),
-    url(r"^debug/oauth/authorize/$", DebugOAuthAuthorizeView.as_view()),
-    url(r"^debug/oauth/authorize/error/$", DebugOAuthAuthorizeErrorView.as_view()),
-    url(r"^debug/chart-renderer/$", DebugChartRendererView.as_view()),
+    re_path("^debug/mail/new-processing-issues", DebugNewProcessingIssuesEmailView.as_view()),
+    re_path("^debug/mail/sso-linked", DebugSsoLinkedEmailView.as_view()),
+    re_path("^debug/mail/sso-unlinked/no-password", DebugSsoUnlinkedNoPasswordEmailView.as_view()),
+    re_path("^debug/mail/sso-unlinked", DebugSsoUnlinkedEmailView.as_view()),
+    re_path("^debug/mail/incident-activity", DebugIncidentActivityEmailView.as_view()),
+    re_path("^debug/mail/incident-trigger", DebugIncidentTriggerEmailView.as_view()),
+    re_path("^debug/mail/setup-2fa", DebugSetup2faEmailView.as_view()),
+    re_path("^debug/embed/error-page", DebugErrorPageEmbedView.as_view()),
+    re_path("^debug/trigger-error", DebugTriggerErrorView.as_view()),
+    re_path("^debug/auth-confirm-identity", debug_auth_views.DebugAuthConfirmIdentity.as_view()),
+    re_path("^debug/auth-confirm-link", debug_auth_views.DebugAuthConfirmLink.as_view()),
+    re_path("^debug/sudo", TemplateView.as_view(template_name="sentry/account/sudo.html")),
+    re_path("^debug/oauth/authorize/error", DebugOAuthAuthorizeErrorView.as_view()),
+    re_path("^debug/oauth/authorize", DebugOAuthAuthorizeView.as_view()),
+    re_path("^debug/chart-renderer", DebugChartRendererView.as_view()),
 ]
diff --git a/src/sentry/web/urls.py b/src/sentry/web/urls.py
index 6baeb3fb9e4f0..a13734776966d 100644
--- a/src/sentry/web/urls.py
+++ b/src/sentry/web/urls.py
@@ -700,6 +700,5 @@
         name="sentry-project-event-redirect",
     ),
     # Legacy
-    # This triggers a false positive for the urls.W002 Django warning
-    url(r"/$", react_page_view),
+    url(r"", react_page_view),
 ]

#sync-getsentry

Update Django version from 2.2.24 to 2.2.27 to resolve dependabot identified vulnerabilities.

Django 2.2.25 included some breaking changes for us in terms of URL route matching.

> Changed in Django 2.2.25:
> In older versions, a full-match wasn’t required for a route which ends with $.

Some route changes were necessary:
- The _legacy_ catch-all route no longer behaved as we expected, so it's been adjusted.
  - For example in 2.2.24, a HTTP request to `/<org.slug>/<project.slug>/settings/plugins/<plugin_slug>/` would match on the intended catch-all, be routed to React land, and then redirected to `/settings/<org.slug>/projects/<project.slug>/plugins/<plugin_slug>/`.
  - In >=2.2.25, a full-match is now required. The above HTTP request fails to match even on the original catch-all resulting in a HTTP response of 404.
- Routes in the debug_urls were not behaving as expected and have been adjusted.
  - I also opted to use `re_path` (from `django.urls`) rather than `url` (from `django.conf.urls`). The latter is an alias to `re_path` in 2.2.x, but is [deprecated starting from Django 3.1.x](https://docs.djangoproject.com/en/3.2/ref/urls/#url).

This PR supersedes:
- #31720 
- #31098