Skip to content

Implement bulk code mappings API endpoint #1074

@romtsn

Description

@romtsn

Context

The existing code mappings API (POST /api/0/organizations/{org}/code-mappings/) requires internal IDs (repositoryId, integrationId, projectId) and only creates one mapping at a time. For CLI usage in multi-module Android projects, we need a single endpoint that accepts human-readable identifiers and bulk creates/updates mappings.

What

Create POST /api/0/organizations/{org}/code-mappings/bulk/ endpoint.

Request format:

{
  "project": "my-android-app",
  "repository": "getsentry/sentry-android",
  "defaultBranch": "main",
  "mappings": [
    {"stackRoot": "com/example/maps", "sourceRoot": "modules/maps/src/main/java/com/example/maps"}
  ]
}

Endpoint logic:

  1. Validate request body via serializer (max 200 mappings)
  2. Resolve project by slug — Project.objects.get(organization=org, slug=..., status=ACTIVE)
  3. Check project access — request.access.has_project_access(project)
  4. Resolve repository by name — Repository.objects.get(organization_id=..., name=..., status=ACTIVE)
  5. Derive integration_id and organization_integration_id from the repository
  6. Validate defaultBranch (required unless Perforce integration)
  7. Loop through mappings — RepositoryProjectPathConfig.objects.update_or_create() keyed on (project, stack_root)
  8. Return per-mapping results (created/updated/error), HTTP 200 on full success, 207 on partial failure

Key decisions:

  • Upsert by (project, stack_root) — matches existing unique constraint
  • Best-effort processing (not atomic)
  • Duplicate stackRoot in same request → last-write-wins
  • Multiple repos with same name → return 409

Reusable code:

  • gen_path_regex_field() from organization_code_mappings.py — path validation
  • BRANCH_NAME_ERROR_MESSAGE — branch regex
  • integration_service.get_organization_integration() — org-integration resolution

Files

  • Create: src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
  • Modify: src/sentry/api/urls.py (register route before code-mappings/{config_id}/ catch-all)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions