Skip to content

:hammer_and_wrench: Sync API Urls to TypeScript

9ffb9e8
Select commit
Loading
Failed to load commit list.
Merged

feat(seer): Add Seer project connected repo endpoint #115199

:hammer_and_wrench: Sync API Urls to TypeScript
9ffb9e8
Select commit
Loading
Failed to load commit list.
@sentry/warden / warden: sentry-backend-bugs completed May 19, 2026 in 11m 24s

2 issues

sentry-backend-bugs: Found 2 issues (1 high, 1 medium)

High

New Seer project-repos endpoints use removed ORM fields, causing FieldError on every request - `src/sentry/api/urls.py:2462-2473`

SeerProjectRepository no longer has project or repository FK fields — they were removed by migration 0016_remove_old_fks (SafeRemoveField with MOVE_TO_PENDING removes the fields from the Django model state). The current model in src/sentry/seer/models/project_repository.py only declares the project_repository FK to sentry.ProjectRepository.

However, the new endpoints and helpers introduced in this PR repeatedly reference the removed fields:

  • src/sentry/seer/endpoints/project_seer_repos.py:
    • _get_project_repos_queryset (≈ line 132): SeerProjectRepository.objects.filter(project=project, repository__status=ObjectStatus.ACTIVE).select_related("repository") and annotation Replace("repository__provider", ...).
    • _serialize_project_repo (≈ line 67): project_repo.repository attribute access.
    • _get_project_repo / OrganizationSeerProjectRepoDetailsEndpoint.delete (≈ line 332): .filter(project=project, repository_id=repo_id, repository__status=...).
  • src/sentry/seer/autofix/utils.py:
    • add_seer_project_repos (≈ line 891): .filter(project=project, repository_id__in=repo_ids) and SeerProjectRepository.objects.create(project=project, repository_id=...).
    • replace_all_seer_project_repos (≈ line 916): .filter(project=project).delete() and .create(project=project, repository_id=...).

Existing working code (e.g. read_preference_from_sentry_db, has_project_connected_repos) correctly traverses project_repository__project=... and project_repository__repository__status=.... The new endpoints/helpers will raise django.core.exceptions.FieldError: Cannot resolve keyword 'project' into field (and repository) on every GET/POST/PUT/DELETE, and _serialize_project_repo will additionally raise AttributeError because repository is no longer a direct relation.

Fix: replace project=project with project_repository__project=project, repository_id=.../repository_id__in=... with project_repository__repository_id=.../__in=..., repository__status=... with project_repository__repository__status=..., repository__provider/repository__name with project_repository__repository__provider/__name, and access project_repo.project_repository.repository in _serialize_project_repo. For create/delete, construct/select via the ProjectRepository link (e.g. look up or create the ProjectRepository row and pass project_repository=<pr>).

Also found at:

  • src/sentry/seer/endpoints/project_seer_repos.py:250-282

Medium

Duplicate-repo check runs outside the transaction, causing unhandled IntegrityError under concurrent requests - `src/sentry/seer/autofix/utils.py:895-904`

The connected_ids duplicate check (lines 895–901) is performed before the transaction begins, so two concurrent requests for the same project+repo IDs can both pass the check; the second SeerProjectRepository.objects.create() then violates the unique constraint and raises an unhandled IntegrityError (500). Move the check inside the transaction after select_for_update.


⏱ 10m 24s · 2.8M in / 78.5k out · $3.36

Annotations

Check failure on line 2473 in src/sentry/api/urls.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: sentry-backend-bugs

New Seer project-repos endpoints use removed ORM fields, causing FieldError on every request

`SeerProjectRepository` no longer has `project` or `repository` FK fields — they were removed by migration `0016_remove_old_fks` (SafeRemoveField with MOVE_TO_PENDING removes the fields from the Django model state). The current model in `src/sentry/seer/models/project_repository.py` only declares the `project_repository` FK to `sentry.ProjectRepository`.

However, the new endpoints and helpers introduced in this PR repeatedly reference the removed fields:

- `src/sentry/seer/endpoints/project_seer_repos.py`:
  - `_get_project_repos_queryset` (≈ line 132): `SeerProjectRepository.objects.filter(project=project, repository__status=ObjectStatus.ACTIVE).select_related("repository")` and annotation `Replace("repository__provider", ...)`.
  - `_serialize_project_repo` (≈ line 67): `project_repo.repository` attribute access.
  - `_get_project_repo` / `OrganizationSeerProjectRepoDetailsEndpoint.delete` (≈ line 332): `.filter(project=project, repository_id=repo_id, repository__status=...)`.
- `src/sentry/seer/autofix/utils.py`:
  - `add_seer_project_repos` (≈ line 891): `.filter(project=project, repository_id__in=repo_ids)` and `SeerProjectRepository.objects.create(project=project, repository_id=...)`.
  - `replace_all_seer_project_repos` (≈ line 916): `.filter(project=project).delete()` and `.create(project=project, repository_id=...)`.

Existing working code (e.g. `read_preference_from_sentry_db`, `has_project_connected_repos`) correctly traverses `project_repository__project=...` and `project_repository__repository__status=...`. The new endpoints/helpers will raise `django.core.exceptions.FieldError: Cannot resolve keyword 'project' into field` (and `repository`) on every GET/POST/PUT/DELETE, and `_serialize_project_repo` will additionally raise `AttributeError` because `repository` is no longer a direct relation.

Fix: replace `project=project` with `project_repository__project=project`, `repository_id=...`/`repository_id__in=...` with `project_repository__repository_id=...`/`__in=...`, `repository__status=...` with `project_repository__repository__status=...`, `repository__provider`/`repository__name` with `project_repository__repository__provider`/`__name`, and access `project_repo.project_repository.repository` in `_serialize_project_repo`. For `create`/`delete`, construct/select via the `ProjectRepository` link (e.g. look up or create the `ProjectRepository` row and pass `project_repository=<pr>`).

Check failure on line 282 in src/sentry/seer/endpoints/project_seer_repos.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: sentry-backend-bugs

[A9S-DU5] New Seer project-repos endpoints use removed ORM fields, causing FieldError on every request (additional location)

`SeerProjectRepository` no longer has `project` or `repository` FK fields — they were removed by migration `0016_remove_old_fks` (SafeRemoveField with MOVE_TO_PENDING removes the fields from the Django model state). The current model in `src/sentry/seer/models/project_repository.py` only declares the `project_repository` FK to `sentry.ProjectRepository`.

However, the new endpoints and helpers introduced in this PR repeatedly reference the removed fields:

- `src/sentry/seer/endpoints/project_seer_repos.py`:
  - `_get_project_repos_queryset` (≈ line 132): `SeerProjectRepository.objects.filter(project=project, repository__status=ObjectStatus.ACTIVE).select_related("repository")` and annotation `Replace("repository__provider", ...)`.
  - `_serialize_project_repo` (≈ line 67): `project_repo.repository` attribute access.
  - `_get_project_repo` / `OrganizationSeerProjectRepoDetailsEndpoint.delete` (≈ line 332): `.filter(project=project, repository_id=repo_id, repository__status=...)`.
- `src/sentry/seer/autofix/utils.py`:
  - `add_seer_project_repos` (≈ line 891): `.filter(project=project, repository_id__in=repo_ids)` and `SeerProjectRepository.objects.create(project=project, repository_id=...)`.
  - `replace_all_seer_project_repos` (≈ line 916): `.filter(project=project).delete()` and `.create(project=project, repository_id=...)`.

Existing working code (e.g. `read_preference_from_sentry_db`, `has_project_connected_repos`) correctly traverses `project_repository__project=...` and `project_repository__repository__status=...`. The new endpoints/helpers will raise `django.core.exceptions.FieldError: Cannot resolve keyword 'project' into field` (and `repository`) on every GET/POST/PUT/DELETE, and `_serialize_project_repo` will additionally raise `AttributeError` because `repository` is no longer a direct relation.

Fix: replace `project=project` with `project_repository__project=project`, `repository_id=...`/`repository_id__in=...` with `project_repository__repository_id=...`/`__in=...`, `repository__status=...` with `project_repository__repository__status=...`, `repository__provider`/`repository__name` with `project_repository__repository__provider`/`__name`, and access `project_repo.project_repository.repository` in `_serialize_project_repo`. For `create`/`delete`, construct/select via the `ProjectRepository` link (e.g. look up or create the `ProjectRepository` row and pass `project_repository=<pr>`).

Check warning on line 904 in src/sentry/seer/autofix/utils.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: sentry-backend-bugs

Duplicate-repo check runs outside the transaction, causing unhandled IntegrityError under concurrent requests

The `connected_ids` duplicate check (lines 895–901) is performed before the transaction begins, so two concurrent requests for the same project+repo IDs can both pass the check; the second `SeerProjectRepository.objects.create()` then violates the unique constraint and raises an unhandled `IntegrityError` (500). Move the check inside the transaction after `select_for_update`.