Skip to content

ref(db): Migrate create_or_update to update_or_create in five modules#112906

Open
vgrozdanic wants to merge 2 commits intomasterfrom
vgrozdanic/ref/migrate-create-or-update-to-update-or-create-v2
Open

ref(db): Migrate create_or_update to update_or_create in five modules#112906
vgrozdanic wants to merge 2 commits intomasterfrom
vgrozdanic/ref/migrate-create-or-update-to-update-or-create-v2

Conversation

@vgrozdanic
Copy link
Copy Markdown
Member

@vgrozdanic vgrozdanic commented Apr 14, 2026

Replace the legacy Sentry create_or_update helper with Django's update_or_create across five call sites, removing them from the usage allowlist.

create_or_update predates Django's update_or_create and is being deprecated. A CI test enforces an allowlist of remaining usages; this PR removes four files from that list.

FeatureAdoptioncomplete=True was in the filter but is not part of the unique_together constraint on (organization, feature_id). With update_or_create, that would cause an IntegrityError if a row existed with complete=False. Fixed by moving complete=True into defaults so the filter aligns with the unique constraint.

OrganizationOption.set_valuevalues=defaults=. The old return value bool(created) or inst > 0 guarded against 0 rows affected, which cannot happen with update_or_create — always returns True now.

OrganizationOnboardingTaskvalues= maps to defaults= (applied on create and update); the create-only user_id moves to create_defaults merged with values, since Django uses create_defaults exclusively for the insert path.

Onboarding tasks endpointrows_affected is no longer meaningful since update_or_create always returns an instance. try_mark_onboarding_complete is called unconditionally; it is idempotent (early-exits if onboarding:complete option already exists, and deduplicates the analytics event via a unique constraint).

mockdatacreate_or_update(member, team) with no values becomes get_or_create; defaults= (which was create-only in the legacy API) becomes create_defaults=.

Supersedes #111784 (rebased fresh on master to avoid stale CI failures).

Requires https://github.com/getsentry/getsentry/pull/19890

Replace the legacy Sentry create_or_update helper with Django's
update_or_create across five call sites, removing them from the
usage allowlist.

- FeatureAdoption: move complete=True into defaults to align with
  the unique_together constraint on (organization, feature_id)
- OrganizationOption.set_value: values= becomes defaults=, always
  returns True since update_or_create guarantees a row
- OrganizationOnboardingTask: values= maps to defaults=, user_id
  moves to create_defaults for insert-only semantics
- Onboarding tasks endpoint: call try_mark_onboarding_complete
  unconditionally since update_or_create always returns an instance
- mockdata: create_or_update with no values becomes get_or_create,
  defaults= becomes create_defaults= for insert-only field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Apr 14, 2026
@vgrozdanic vgrozdanic marked this pull request as ready for review April 14, 2026 13:12
@vgrozdanic vgrozdanic requested review from a team as code owners April 14, 2026 13:12
Copy link
Copy Markdown
Member

@markstory markstory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants