feat(integrations): Add bulk code mappings API endpoint#109785
feat(integrations): Add bulk code mappings API endpoint#109785
Conversation
|
🚨 Warning: This pull request contains Frontend and Backend changes! It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently. Have questions? Please ask in the |
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
a520ca4 to
1b9c863
Compare
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
7f92c45 to
0cfaac3
Compare
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
388490d to
f859e09
Compare
59cf81a to
0b46407
Compare
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
a6f20e0 to
c0a84d0
Compare
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Show resolved
Hide resolved
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Show resolved
Hide resolved
When a repository doesn't exist in Sentry but the provider field is specified, the endpoint now verifies the repo exists on the integration (e.g. GitHub) and auto-creates the Repository record. This follows the pattern used by derived code mappings. Co-Authored-By: Claude Opus 4.6 <[email protected]>
The identifier-then-name matching pattern was duplicated in both _auto_create_repository and get_repository_default_branch. Extract it into a shared static method on RepositoryIntegration. Co-Authored-By: Claude Opus 4.6 <[email protected]>
a2bdd2f to
f59e800
Compare
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
…or_create by provider region_silo_endpoint was renamed to cell_silo_endpoint on master. Also add provider to get_or_create lookup fields in _auto_create_repository to prevent MultipleObjectsReturned when repos with the same name exist for different providers. Co-Authored-By: Claude Opus 4.6 <[email protected]>
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Show resolved
Hide resolved
e0990aa to
de34ccc
Compare
thanks for the suggestions! Added it in this PR too as well as inferring the branch name and creating a new repo if it doesn't exist |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Outdated
Show resolved
Hide resolved
de34ccc to
d64c9f8
Compare
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Show resolved
Hide resolved
get_or_create on (name, organization_id, provider) can raise MultipleObjectsReturned since the unique constraint is on (organization_id, provider, external_id). Also filter by status=ACTIVE to avoid returning inactive repos. Co-Authored-By: Claude Opus 4.6 <[email protected]>
d64c9f8 to
a042869
Compare
src/sentry/integrations/api/endpoints/organization_code_mappings_bulk.py
Show resolved
Hide resolved
| organization_id=organization.id, | ||
| provider=repo_provider, | ||
| integration_id=org_int.integration_id, | ||
| external_id=repo_info.get("identifier", ""), |
| organization_id=organization.id, | ||
| provider=repo_provider, | ||
| integration_id=org_int.integration_id, | ||
| external_id=repo_info.get("identifier", ""), |
…k code mappings (#109786) ## Summary - Add tests for `org:ci` token authentication (sentry-cli CI use case) - Add IDOR prevention tests (cross-org project and repo access) - Add permission tests (project access check, org member access) - Add edge case tests (duplicate stackRoots in request, multiple repos with same name) Depends on #109785 Closes getsentry/sentry-android-gradle-plugin#1075 ## Test plan - [x] 7 additional tests (27 total), all passing - [x] Pre-commit passes
_#skip-changelog_ Add the `sentry-cli code-mappings upload` subcommand group and the `upload` subcommand with file parsing and validation. This is the first in a stack of 4 PRs to support bulk uploading code mappings from a JSON file — useful for Java/Android multi-module projects that need dozens of mappings. This PR adds: - Command scaffold following the `repos`/`deploys` pattern - JSON file reading and validation (empty arrays, empty stackRoot/sourceRoot) - CLI args: positional `PATH`, `--repo`, `--default-branch` - Help and no-subcommand trycmd integration tests Stack: **#3207** → #3208 → #3209 → #3210 Backend PRs: getsentry/sentry#109783, getsentry/sentry#109785, getsentry/sentry#109786 Closes getsentry/sentry-android-gradle-plugin#1076 Closes getsentry/sentry-android-gradle-plugin#1077 --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
…3208) *#skip-changelog* When `--repo` or `--default-branch` are not provided, infer them from the<br>local git repository. Uses the configured VCS remote (SENTRY_VCS_REMOTE / ini)<br>first, then falls back to best-effort remote detection (upstream > origin > first). Also extracts `find_best_remote()` as a shared utility in `src/utils/vcs.rs`,<br>replacing the inline logic that was duplicated in `git_repo_base_repo_name_preserve_case`. Stack: #3207 → [#3208](<#3208>) → [#3209](<#3209>) → [#3210](<#3210>) Backend PRs: [getsentry/sentry#109783](<getsentry/sentry#109783>), [getsentry/sentry#109785](<getsentry/sentry#109785>), [getsentry/sentry#109786](<getsentry/sentry#109786>) Closes [GRADLE-79](https://linear.app/getsentry/issue/GRADLE-79/add-git-inference-for-repo-name-and-default-branch) --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
…#3209) _#skip-changelog_ Connect the `code-mappings upload` command to the bulk code mappings API endpoint (`POST /api/0/organizations/{org}/code-mappings/bulk/`). Adds: - `bulk_upload_code_mappings()` method on `AuthenticatedApi` - Request/response data types in `src/api/data_types/code_mappings.rs` - Summary table and error reporting in the command output - Happy-path integration test with mock endpoint Stack: #3207 → #3208 → **#3209** → #3210 Backend PRs: getsentry/sentry#109783, getsentry/sentry#109785, getsentry/sentry#109786 Closes getsentry/sentry-android-gradle-plugin#1079 --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
_#skip-changelog_ Split large mapping files into batches of 300 (the backend limit) per request. Each batch is sent sequentially with progress reporting, and results are merged into a single summary. Also changes the output table to only show error rows — for large uploads (hundreds of mappings), printing every row would flood the terminal. Successful mappings are reflected in the summary counts instead. Stack: #3207 → #3208 → #3209 → **#3210** Backend PRs: getsentry/sentry#109783, getsentry/sentry#109785, getsentry/sentry#109786 --------- Co-authored-by: Claude Opus 4.6 <[email protected]>

Summary
POST /api/0/organizations/{org}/code-mappings/bulk/endpoint that accepts human-readable identifiers (project slug, repo name) instead of internal IDsupdate_or_createloop for best-effort upsert with per-mapping status reportingDepends on #109783
Closes getsentry/sentry-android-gradle-plugin#1074
Test plan