Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion migrations_lockfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ To resolve this, rebase against latest master and regenerate your migration. Thi
will then be regenerated, and you should be able to merge without conflicts.

nodestore: 0002_nodestore_no_dictfield
sentry: 0243_delete_visualstudio_repo_data
sentry: 0244_organization_and_integration_foreign_keys
social_auth: 0001_initial
2 changes: 1 addition & 1 deletion src/sentry/db/models/fields/foreignkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class FlexibleForeignKey(ForeignKey):
def __init__(self, *args, **kwargs):
kwargs.setdefault("on_delete", models.CASCADE)
return super().__init__(*args, **kwargs)
super().__init__(*args, **kwargs)

def db_type(self, connection):
# This is required to support BigAutoField (or anything similar)
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/db/models/fields/onetoone.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
class OneToOneCascadeDeletes(OneToOneField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("on_delete", models.CASCADE)
return super().__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
5 changes: 2 additions & 3 deletions src/sentry/integrations/utils/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from typing import TYPE_CHECKING, Mapping, Sequence

from sentry import features
from sentry.models import GroupAssignee
from sentry.models import Group, GroupAssignee, Project, User
from sentry.tasks.integrations import sync_assignee_outbound

if TYPE_CHECKING:
from sentry.models import Group, Integration, Organization
from sentry.models import Integration, Organization


def where_should_sync(
Expand Down Expand Up @@ -56,7 +56,6 @@ def sync_group_assignee_inbound(
assign linked groups to matching users. Checks project membership.
Returns a list of groups that were successfully assigned.
"""
from sentry.models import Group, Project, User

logger = logging.getLogger(f"sentry.integrations.{integration.provider}")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Generated by Django 2.2.24 on 2021-10-11 22:06

import django.db.models.deletion
from django.db import migrations

import sentry.db.models.fields.foreignkey


class Migration(migrations.Migration):
# This flag is used to mark that a migration shouldn't be automatically run in
# production. We set this to True for operations that we think are risky and want
# someone from ops to run manually and monitor.
# General advice is that if in doubt, mark your migration as `is_dangerous`.
# Some things you should always mark as dangerous:
# - Large data migrations. Typically we want these to be run manually by ops so that
# they can be monitored. Since data migrations will now hold a transaction open
# this is even more important.
# - Adding columns to highly active tables, even ones that are NULL.
is_dangerous = False

# This flag is used to decide whether to run this migration in a transaction or not.
# By default we prefer to run in a transaction, but for migrations where you want
# to `CREATE INDEX CONCURRENTLY` this needs to be set to False. Typically you'll
# want to create an index concurrently when adding one to an existing table.
# You'll also usually want to set this to `False` if you're writing a data
# migration, since we don't want the entire migration to run in one long-running
# transaction.
atomic = True

dependencies = [
("sentry", "0243_delete_visualstudio_repo_data"),
]

operations = [
migrations.SeparateDatabaseAndState(
database_operations=[],
state_operations=[
migrations.AddField(
model_name="externalissue",
name="integration",
field=sentry.db.models.fields.foreignkey.FlexibleForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="sentry.Integration",
db_constraint=False,
),
),
migrations.AddField(
model_name="externalissue",
name="organization",
field=sentry.db.models.fields.foreignkey.FlexibleForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="sentry.Organization",
db_constraint=False,
),
),
migrations.AddField(
model_name="grouplink",
name="group",
field=sentry.db.models.fields.foreignkey.FlexibleForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="sentry.Group",
db_constraint=False,
),
),
migrations.AddField(
model_name="grouplink",
name="project",
field=sentry.db.models.fields.foreignkey.FlexibleForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="sentry.Project",
db_constraint=False,
),
),
migrations.AlterUniqueTogether(
name="externalissue",
unique_together={("organization", "integration", "key")},
),
migrations.AlterUniqueTogether(
name="grouplink",
unique_together={("group", "linked_type", "linked_id")},
),
migrations.RemoveField(
model_name="externalissue",
name="integration_id",
),
migrations.RemoveField(
model_name="externalissue",
name="organization_id",
),
migrations.RemoveField(
model_name="grouplink",
name="group_id",
),
migrations.RemoveField(
model_name="grouplink",
name="project_id",
),
],
)
]
17 changes: 10 additions & 7 deletions src/sentry/models/externalissue.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.db.models import QuerySet
from django.utils import timezone

from sentry.db.models import BaseManager, BoundedPositiveIntegerField, JSONField, Model, sane_repr
from sentry.db.models import BaseManager, FlexibleForeignKey, JSONField, Model, sane_repr

if TYPE_CHECKING:
from sentry.models import Integration
Expand All @@ -16,10 +16,9 @@ class ExternalIssueManager(BaseManager):
def get_for_integration(
self, integration: Integration, external_issue_key: str | None = None
) -> QuerySet:
"""TODO(mgaeta): Migrate the model to use FlexibleForeignKey."""
kwargs = dict(
integration_id=integration.id,
organization_id__in={_.id for _ in integration.organizations.all()},
integration=integration,
organization__organizationintegration__integration=integration,
)

if external_issue_key is not None:
Expand All @@ -31,8 +30,12 @@ def get_for_integration(
class ExternalIssue(Model):
__include_in_export__ = False

organization_id = BoundedPositiveIntegerField()
integration_id = BoundedPositiveIntegerField()
# The foreign key here is an `int`, not `bigint`.
organization = FlexibleForeignKey("sentry.Organization", db_constraint=False)

# The foreign key here is an `int`, not `bigint`.
integration = FlexibleForeignKey("sentry.Integration", db_constraint=False)

key = models.CharField(max_length=128) # example APP-123 in jira
date_added = models.DateTimeField(default=timezone.now)
title = models.TextField(null=True)
Expand All @@ -44,7 +47,7 @@ class ExternalIssue(Model):
class Meta:
app_label = "sentry"
db_table = "sentry_externalissue"
unique_together = (("organization_id", "integration_id", "key"),)
unique_together = (("organization", "integration", "key"),)

__repr__ = sane_repr("organization_id", "integration_id", "key")

Expand Down
10 changes: 5 additions & 5 deletions src/sentry/models/grouplink.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
BaseManager,
BoundedBigIntegerField,
BoundedPositiveIntegerField,
FlexibleForeignKey,
JSONField,
Model,
sane_repr,
Expand All @@ -22,9 +23,8 @@

class GroupLinkManager(BaseManager):
def get_group_issues(self, group: Group, external_issue_id: str | None = None) -> QuerySet:
"""TODO(mgaeta): Migrate the model to use FlexibleForeignKey."""
kwargs = dict(
group_id=group.id,
group=group,
project_id=group.project_id,
linked_type=GroupLink.LinkedType.issue,
relationship=GroupLink.Relationship.references,
Expand Down Expand Up @@ -53,8 +53,8 @@ class LinkedType:
pull_request = 2
issue = 3

group_id = BoundedBigIntegerField()
project_id = BoundedBigIntegerField(db_index=True)
group = FlexibleForeignKey("sentry.Group", db_constraint=False)
project = FlexibleForeignKey("sentry.Project", db_constraint=False, db_index=True)
linked_type = BoundedPositiveIntegerField(
default=LinkedType.commit,
choices=(
Expand All @@ -76,6 +76,6 @@ class LinkedType:
class Meta:
app_label = "sentry"
db_table = "sentry_grouplink"
unique_together = (("group_id", "linked_type", "linked_id"),)
unique_together = (("group", "linked_type", "linked_id"),)

__repr__ = sane_repr("group_id", "linked_type", "linked_id", "relationship", "datetime")